File size: 6,728 Bytes
29691f6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
#!/usr/bin/env python3
"""

基础测试

测试项目的基本功能

"""

import os
import sys
import torch
import torch.nn as nn
import numpy as np

# 添加项目根目录到Python路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))

from src.models.unet_light import UNetLight, TimestepEmbedding, ResNetBlock
from src.models.attention import MemoryEfficientAttention
from src.models.diffusion import DiffusionProcess


def test_timestep_embedding():
    """测试时间步嵌入"""
    print("测试时间步嵌入...")
    
    embedding_dim = 256
    time_embed_dim = 512
    
    embedder = TimestepEmbedding(embedding_dim, time_embed_dim)
    
    # 测试前向传播
    timesteps = torch.tensor([100, 200, 300])
    embeddings = embedder(timesteps)
    
    assert embeddings.shape == (3, time_embed_dim)
    print(f"  形状正确: {embeddings.shape}")
    
    return embedder


def test_resnet_block():
    """测试残差块"""
    print("测试残差块...")
    
    in_channels = 64
    out_channels = 128
    time_embed_dim = 256
    
    block = ResNetBlock(in_channels, out_channels, time_embed_dim)
    
    # 测试前向传播
    x = torch.randn(2, in_channels, 32, 32)
    time_emb = torch.randn(2, time_embed_dim)
    
    output = block(x, time_emb)
    
    assert output.shape == (2, out_channels, 32, 32)
    print(f"  形状正确: {output.shape}")
    
    # 测试跳跃连接
    block_same = ResNetBlock(in_channels, in_channels, time_embed_dim)
    output_same = block_same(x, time_emb)
    
    assert output_same.shape == x.shape
    print(f"  跳跃连接正确")
    
    return block


def test_attention():
    """测试注意力机制"""
    print("测试注意力机制...")
    
    dim = 256
    num_heads = 8
    
    attention = MemoryEfficientAttention(dim, num_heads)
    
    # 测试前向传播
    x = torch.randn(2, 16, dim)  # [batch, seq_len, dim]
    output = attention(x)
    
    assert output.shape == x.shape
    print(f"  形状正确: {output.shape}")
    
    return attention


def test_unet_light():
    """测试轻量UNet"""
    print("测试轻量UNet...")
    
    config = {
        'model': {
            'in_channels': 4,
            'out_channels': 4,
            'base_channels': 32,  # 测试用小模型
            'channel_mults': [1, 2, 4],
            'num_res_blocks': 1,
            'attention_resolutions': [8],
            'dropout': 0.0,
            'use_checkpoint': False,
            'num_heads': 4,
            'context_dim': 256,
            'use_linear_projection': True,
            'time_embed_dim': 128
        }
    }
    
    model = UNetLight(config)
    
    # 测试前向传播
    batch_size = 2
    x = torch.randn(batch_size, 4, 64, 64)
    timesteps = torch.randint(0, 1000, (batch_size,))
    context = torch.randn(batch_size, 77, 256)
    
    output = model(x, timesteps, context)
    
    assert output.shape == x.shape
    print(f"  形状正确: {output.shape}")
    
    # 测试梯度检查点
    model.enable_gradient_checkpointing()
    print(f"  梯度检查点已启用")
    
    return model


def test_diffusion_process():
    """测试扩散过程"""
    print("测试扩散过程...")
    
    config = {
        'diffusion': {
            'beta_schedule': 'linear',
            'beta_start': 0.0001,
            'beta_end': 0.02,
            'num_train_timesteps': 100,
            'num_inference_timesteps': 20
        }
    }
    
    diffusion = DiffusionProcess(config)
    
    # 测试前向扩散
    x_start = torch.randn(2, 3, 32, 32)
    t = torch.randint(0, 100, (2,))
    
    x_noisy = diffusion.q_sample(x_start, t)
    
    assert x_noisy.shape == x_start.shape
    print(f"  前向扩散形状正确: {x_noisy.shape}")
    
    # 测试参数提取
    extracted = diffusion.extract(diffusion.sqrt_alphas_cumprod, t, x_start.shape)
    assert extracted.shape == (2, 1, 1, 1)
    print(f"  参数提取形状正确: {extracted.shape}")
    
    return diffusion


def test_memory_efficiency():
    """测试内存效率"""
    print("测试内存效率...")
    
    # 测试模型在不同批次大小下的内存使用
    config = {
        'model': {
            'in_channels': 4,
            'out_channels': 4,
            'base_channels': 32,
            'channel_mults': [1, 2],
            'num_res_blocks': 1,
            'attention_resolutions': [],
            'dropout': 0.0,
            'use_checkpoint': False,
            'num_heads': 4,
            'context_dim': 256,
            'use_linear_projection': True,
            'time_embed_dim': 128
        }
    }
    
    model = UNetLight(config)
    model.eval()
    
    if torch.cuda.is_available():
        device = torch.device('cuda')
        model = model.to(device)
        
        print("  GPU内存测试:")
        
        for batch_size in [1, 2, 4]:
            # 清空缓存
            torch.cuda.empty_cache()
            
            # 记录初始内存
            initial_memory = torch.cuda.memory_allocated()
            
            # 前向传播
            x = torch.randn(batch_size, 4, 64, 64, device=device)
            t = torch.randint(0, 1000, (batch_size,), device=device)
            context = torch.randn(batch_size, 77, 256, device=device)
            
            with torch.no_grad():
                _ = model(x, t, context)
            
            # 记录峰值内存
            peak_memory = torch.cuda.max_memory_allocated()
            memory_used = (peak_memory - initial_memory) / 1024**3  # GB
            
            print(f"    批次大小 {batch_size}: {memory_used:.2f} GB")
    
    else:
        print("  GPU不可用,跳过内存测试")
    
    return model


def run_all_tests():
    """运行所有测试"""
    print("=" * 60)
    print("运行Lumina基础测试")
    print("=" * 60)
    
    try:
        # 测试各个组件
        test_timestep_embedding()
        test_resnet_block()
        test_attention()
        test_unet_light()
        test_diffusion_process()
        test_memory_efficiency()
        
        print("\n" + "=" * 60)
        print("所有测试通过!")
        print("=" * 60)
        
        return True
    
    except Exception as e:
        print(f"\n测试失败: {e}")
        import traceback
        traceback.print_exc()
        return False


if __name__ == "__main__":
    success = run_all_tests()
    sys.exit(0 if success else 1)