compute-sanitizer同时报内存越界与分配内的CUDA错误解析求助
首先明确这个“矛盾”错误的本质:计算sanitizer检测到的是你当前操作的矩阵/张量的内存越界,而非整个分配内存块的越界。虽然错误地址落在你分配的内存块范围内,但它并不属于当前batch中某个矩阵的合法数据区域,所以被判定为非法访问。
结合你的错误日志(来自cublasLt的批量矩阵乘法内核),具体原因和排查方向如下:
核心原因分析
libcublas的矩阵乘法内核是根据你传入的维度参数、步长(stride)、batch size来计算内存访问位置的。只要内核计算出的地址超出了单个矩阵(或当前batch对应的矩阵区域)的有效范围,哪怕这个地址还在你分配的大内存块里,就会触发越界错误。常见的诱因包括:
- 维度参数不匹配:比如你传入的M/N/K维度与实际存储的矩阵维度不符,或者batch size设置错误,导致内核试图访问某个batch的矩阵之外的区域。
- 步长(stride)设置错误:这是批量矩阵乘法中最容易踩坑的点。如果行/列步长小于矩阵的实际维度,或者batch步长小于单个矩阵的内存占用,内核会错误地访问到相邻batch的内存,或者矩阵内部的无效区域。
- 输出矩阵的布局与内核预期不符:比如你手动分配的内存布局(比如对齐方式)和cublasLt要求的不匹配,导致内核计算的访问地址偏离了合法区域。
具体排查步骤
核对所有cublasLtSSSMatmul参数
打印并验证传入的M、N、K、batch size,以及输入/输出矩阵的行步长、列步长、batch步长。重点确认:- 单个矩阵的内存占用:
M * N * sizeof(float)(输出矩阵) - batch步长是否大于等于单个矩阵的内存占用,确保每个batch的矩阵区域不重叠
- 总内存分配大小是否满足:
batch_size * 单个矩阵最大内存占用 + 对齐开销
- 单个矩阵的内存占用:
计算错误地址的位置
从错误日志中提取关键地址,计算偏移量:分配起始地址:0x7fd8aa000000 错误访问地址:0x7fd8c0000224 偏移量 = 0x7fd8c0000224 - 0x7fd8aa000000 = 0x16000224 字节 ≈ 358.4MB 总分配内存:503316480 字节 = 480MB这个偏移确实在分配范围内,接下来计算该偏移对应的batch索引和单矩阵内的偏移:
假设单个输出矩阵占用S字节,那么batch索引为偏移量 // S,单矩阵内偏移为偏移量 % S。如果单矩阵内偏移大于等于单个矩阵的实际大小,就说明步长或batch size设置错误。简化测试用例
- 先将batch size改为1,测试单矩阵乘法是否正常,排除单矩阵维度或步长的问题
- 使用极小的维度(比如M=N=K=2,batch size=2)进行测试,手动计算每个矩阵的内存区域,对比内核访问的地址是否合法
排查库版本问题
你使用的是CUDA 11.5,可查阅CUDA release notes确认该版本的cublasLt是否存在批量矩阵乘法的已知bug。如果上述排查都没问题,可以尝试升级到更高版本的CUDA(比如11.7或12.x)验证是否解决问题。
内容的提问来源于stack exchange,提问作者lacker

