原帖是一维信号 CNN,CPU 能跑,GPU 在 fc1 的线性运算失败;同步调试后从分配错误变成了执行错误:
RuntimeError: CUDA error: CUBLAS_STATUS_EXECUTION_FAILED when calling `cublasSgemm( handle, opa, opb, m, n, k, &alpha, a, lda, b, ldb, &beta, c, ldc)`
先核对真正送进 fc1 的张量
原题只给了信号载入与转置,没有完整卷积结构,因此无法从 3000 点信号直接推出 fc1 的 in_features。cuBLAS 执行错误也没有给出足够证据证明硬件损坏。同步调试后的首次失败点、输入最后一维和权重形状,是更可靠的下一步。
这并不能证明显卡损坏。先从发生失败的矩阵运算检查实际输入,不要把原始信号 [B,3000,1] 当成已经展平后的特征。
在模型 forward 中 x = self.fc1(x) 前插入:
print("josh050608")
print("features:", x.shape, x.dtype, x.device, x.stride())
print("weight:", self.fc1.weight.shape, self.fc1.weight.dtype, self.fc1.weight.device)
print("finite:", bool(x.isfinite().all()))
x 的最后一维应等于 self.fc1.in_features,dtype 与设备也应匹配。检查展平是否写成 x.flatten(1),避免用错误的 view(-1,...) 意外改变 batch 数。原帖没有贴出卷积结构,不能直接替它指定正确的 in_features。
在新进程中开启 CUDA_LAUNCH_BLOCKING=1 后重跑一个批次;Linux 可用 CUDA_LAUNCH_BLOCKING=1 python train.py。若更早的卷积或索引才是首个失败操作,应先修复它。
若形状与设备均正确,用同样 dtype 做很小的 CUDA 矩阵乘法,再逐步增加到该层尺寸,并记录 torch/CUDA 构建、GPU 与驱动版本。小矩阵也失败时查环境;只在大尺寸失败时结合 memory_summary 与 nvidia-smi 看资源压力。不要同时改 batch、驱动和网络,避免丢失区分线索。
修复后应验证同一批数据在 CPU/GPU 的输出形状一致,数值在所用精度允许的范围内接近,并能完成反向。
给真实层挂临时检查,比猜展平结果可靠
若不方便修改 forward,可在模型构建后给 model.fc1 挂前置 hook。batch_x 是已经转置并送到目标设备的一小批真实信号,务必来自失败路径:
def inspect_linear(layer, args):
features = args[0]
print("linear input:", features.shape, features.dtype, features.device)
print("linear weight:", layer.weight.shape, layer.weight.dtype, layer.weight.device)
assert features.shape[-1] == layer.in_features
assert features.dtype == layer.weight.dtype
assert features.device == layer.weight.device
handle = model.fc1.register_forward_pre_hook(inspect_linear)
try:
prediction = model(batch_x)
finally:
handle.remove()
下面以合成 1D CNN 演示如何确定展平宽度,不声称它就是原题网络:
import torch
from torch import nn
features = nn.Sequential(nn.Conv1d(1, 4, 3), nn.ReLU(), nn.AdaptiveAvgPool1d(5))
signals = torch.randn(2, 30, 1)
activation = features(signals.transpose(1, 2))
flat = activation.flatten(1)
head = nn.Linear(4 * 5, 1)
assert flat.shape == (2, head.in_features)
result = head(flat)
result.square().mean().backward()
assert result.shape == (2, 1)
assert head.weight.grad is not None
print("activation/flat/result:", activation.shape, flat.shape, result.shape)
真实网络不一定需要 AdaptiveAvgPool;应先确认输出布局,再选择固定输入长度、调整全连接宽度或有意池化。不要仅为满足乘法而用 view 把 batch 维揉进特征维。
原题还按 batch 编号切标签,如果将来让 loader 打乱数据,这种外部切片会错配标签;应让信号与目标来自同一个 Dataset。它不必是此次 cuBLAS 的根因,但在验证恢复训练时必须保证输入目标对应,避免错误消失却训练了错标签。
参考:原始求助帖;技术依据:Linear(2.5)、PyTorch CUDA 语义(2.5)、CUDA 内存统计(2.5);Conv1d 官方源码(2.5.1)。