Cuda报错:`srcIndex < srcSelectDimSize` failed

Cuda报错:srcIndex < srcSelectDimSize failed

错误简述

我在2024年9月8日开发的模型遇到这个问题。
cuda报错如下

../aten/src/ATen/native/cuda/Indexing.cu:1141: indexSelectLargeIndex: block: [224,0,0], thread: [49,0,0] Assertion `srcIndex < srcSelectDimSize` failed.
../aten/src/ATen/native/cuda/Indexing.cu:1141: indexSelectLargeIndex: block: [224,0,0], thread: [50,0,0] Assertion `srcIndex < srcSelectDimSize` failed.
../aten/src/ATen/native/cuda/Indexing.cu:1141: indexSelectLargeIndex: block: [224,0,0], thread: [51,0,0] Assertion `srcIndex < srcSelectDimSize` failed.
../aten/src/ATen/native/cuda/Indexing.cu:1141: indexSelectLargeIndex: block: [224,0,0], thread: [52,0,0] Assertion `srcIndex < srcSelectDimSize` failed.
../aten/src/ATen/native/cuda/Indexing.cu:1141: indexSelectLargeIndex: block: [224,0,0], thread: [53,0,0] Assertion `srcIndex < srcSelectDimSize` failed.
../aten/src/ATen/native/cuda/Indexing.cu:1141: indexSelectLargeIndex: block: [224,0,0], thread: [54,0,0] Assertion `srcIndex < srcSelectDimSize` failed.
../aten/src/ATen/native/cuda/Indexing.cu:1141: indexSelectLargeIndex: block: [224,0,0], thread: [55,0,0] Assertion `srcIndex < srcSelectDimSize` failed.
../aten/src/ATen/native/cuda/Indexing.cu:1141: indexSelectLargeIndex: block: [224,0,0], thread: [56,0,0] Assertion `srcIndex < srcSelectDimSize` failed.

python端捕捉的额外报错如下:

RuntimeError: CUDA error: CUBLAS_STATUS_EXECUTION_FAILED when calling `cublasLtMatmul( ltHandle, computeDesc.descriptor(), &alpha_val, mat1_ptr, Adesc.descriptor(), mat2_ptr, Bdesc.descriptor(), &beta_val, result_ptr, Cdesc.descriptor(), result_ptr, Cdesc.descriptor(), &heuristicResult.algo, workspace.data_ptr(), workspaceSize, at::cuda::getCurrentCUDAStream())`

背景

我搭建了一个partial_CLIP模型用于处理多模态,使用pretrain模型结果作为输入,然后搭建一个简单的classifier模型来进行分类(只有classifier部分是训练的)。因为场景需要用构造模态缺失场景,所以又搭建了两个模态的缺失场景。同时解决方案是模态重建来解决模态缺失。大致如此。

模态重建

模态重建训练代码如下

@torch.no_grad()
def gen_missing_modality(i2tmodel,x_modalities,index,modal_missing):
    '''
    x_modalities is input values.\\
    index is the index in this batch data.\\
    modal_missing is which modal batch missing.
    '''
    if x_modalities is None or modal_missing is None:
        return
    if modal_missing == 1:
        images,texts,attention_masks = x_modalities[0],x_modalities[1],x_modalities[2]
        img = images[index].clone().detach().to(device)
        img = img.unsqueeze(0)
        i2tmodel.eval()
        gentext = i2tmodel(img,generate_lengths = texts.size(1)).squeeze(0)
        texts[index].copy_(gentext)
        # print(texts[index])
        if texts[index][0] != 49406:
            texts[index][0] = 49406
        for j in range(texts.size(1)):
            if attention_masks[index][j] == 0:
                texts[index,j-1:] = 49407
                break
        texts[index][-1] = 49407
                # xb =xb.to(previous_device)
        # print('after:',texts[index])

因为clip处理的token输入是从49406作为start_token和49407作为ending_token,所以在过程中需要做一些小小的转换。输出过程都很正常。但是将缺失模态补齐后输入到clip中却爆发了开头一幕。

解决方案

(1)起初以为是cuda问题,然后转移了模型到另一个机器上跑,A100 40G,但是仍然报错。所以可以总结该bug必现

(2)然后以为是模型的eval()和train()切换不正常,开始检查(确实有不正常的过程,也算额外的错误),解决完后仍然报错。

(3)解决完上述问题后,私以为tensor张量转移过程可能出现问题,原本在torch.utils.DataLoader类的collate function中处理如下

img = copy.deepcopy(xa[i]).to(device)
img = img.unsqueeze(0)
gentext = self.i2tmodelgen(img,max_length = xb.size(1)).squeeze(0)
xb[i].copy_(gentext)

可以看出我在输出后没有再将gentext返回到cpu中,自信满满改完再跑,仍然出错。。。

gentext = self.i2tmodelgen(img,max_length = xb.size(1)).squeeze(0).cpu()

(4)我又注意到我的img是通过python原生的copy中产生的,我依稀记得torch的tensor有自带的复制函数,后来将上部分代码改成如下

img = xa[i].clone().detach().to(self.device)

不出意外,仍然报错。

(5)感觉代码已经改的七七八八了,从debug的显示中生成的token也不觉得有什么问题,都是很正常的数字。开始做消融实验,将每部分代码都mask掉,看看哪部分报错,以为会是文生图有报错,没想到还是图生文这部分报错。

(6)回过头来了看了一下报错,发现有几个关键词:

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
/tmp/ipykernel_73865/1587976768.py in <module>
     23 #     )[2]
     24     print(inputs[1].max(),inputs[1].min())
---> 25     res = partial_clip(inputs,preclip)
     26     loss = criterion(res, label)
     27     optimizer.zero_grad()

~/anaconda3/envs/py377/lib/python3.7/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
   1192         if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
   1193                 or _global_forward_hooks or _global_forward_pre_hooks):
-> 1194             return forward_call(*input, **kwargs)
   1195         # Do not call functions when jit is used
   1196         full_backward_hooks, non_full_backward_hooks = [], []

~/workspace/FedAdvan/models/multimodal/pretrain_clip.py in forward(self, inputs, basemodel)
    137         # self.pretrained_forward(inputs,basemodel)
    138         # self.forward_input.clear()
--> 139         visual_layer_output,text_layer_output,attention_mask,casual_attention_mask = self.pretrained_forward(inputs,basemodel)
    140         # text_attention_mask,text_casual_attention_mask = self.forward_input[self.text_attention_mask_key],self.forward_input[self.text_casual_attention_mask_key]
    141         # img_attention_mask,img_casual_attention_mask = self.forward_input[self.img_attention_mask_key],self.forward_input[self.img_casual_attention_mask_key]

~/anaconda3/envs/py377/lib/python3.7/site-packages/torch/autograd/grad_mode.py in decorate_context(*args, **kwargs)
     25         def decorate_context(*args, **kwargs):
...
--> 114         return F.linear(input, self.weight, self.bias)
    115 
    116     def extra_repr(self) -> str:

RuntimeError: CUDA error: CUBLAS_STATUS_EXECUTION_FAILED when calling `cublasLtMatmul( ltHandle, computeDesc.descriptor(), &alpha_val, mat1_ptr, Adesc.descriptor(), mat2_ptr, Bdesc.descriptor(), &beta_val, result_ptr, Cdesc.descriptor(), result_ptr, Cdesc.descriptor(), &heuristicResult.algo, workspace.data_ptr(), workspaceSize, at::cuda::getCurrentCUDAStream())`

发现一个很关键的地方,之前cuda报了

Assertion `srcIndex < srcSelectDimSize`

有没有可能输入的数据是数字没问题,但是大小有问题呢?我开始上网搜,发现有网友提到过可能是大小超boundry。在clip将token转成可以学习的向量前是经过了nn.Embedding层,embedding本质上就是将token转成可以学习更加稠密的one-hot向量。one-hot的过程是一对一的,有没有可能我输入的token超过了目标限制?

开始在代码中加入两行

print(inputs[1].max(),inputs[1].min())
res = partial_clip(inputs,preclip)

然后到报错前一次的输出是

tensor(49407, device='cuda:0') tensor(5, device='cuda:0')
tensor(49407, device='cuda:0') tensor(64, device='cuda:0')
tensor(49735, device='cuda:0') tensor(5, device='cuda:0')

前文提到clip输入是49407为结尾,但是我生成的token存在超过了ending token的大小,我模型确实有可能生成超过ending token的token。

i2tmodel = ImageToTextModel(vocab_size=50000)

然后我改成

i2tmodel = ImageToTextModel(vocab_size=49407)

这次训练直接报错(还没生成成功呢)

然后调成49408后,所有训练和测试过程均正常了。

总结

还是得根据结果找原因,不要盲目的乱修改,可以去推测哪部分可能引发问题,比如大小不匹配一定是输入导致大小不匹配,应该去找哪部分会导致大小不匹配。当然我初始版本的代码也有很多问题就是了,吃一堑长一智。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值