1
数学库
ds_read同步有特殊要求?
2025-09-10 16:44:08
181
在使用ds_read加mma指令进行运算时我发现这种情况下`__sycnthreads()`并不能同步线程 开始时代码如下 ```c++ #pragma unroll for (int r = 0; r < 2; r++) { int input_mma_load_offset = ((tid % 64) / 8 + r * 8) * 64 + (tid % 8) * 4; int input_lds_addr = input_mma_load_inner_offset + input_mma_load_offset; input_lds_addr = input_lds_addr * sizeof(float); PREFETCH_LDS(_b, input_lds_addr); int weight_mma_load_offset = ((tid % 64) / 8 + r * 8) * 64 + (tid % 8) * 4; int weight_lds_addr = weight_mma_load_inner_offset + weight_mma_load_offset + weight_dsread_offset; weight_lds_addr = weight_lds_addr * sizeof(float); PREFETCH_LDS(_a, weight_lds_addr); __syncthreads(); _d[0] = __builtin_amdgcn_mmac_f32_16x16x8f32(_a.f2[0], _b.f2[0], _d[0]); _d[1] = __builtin_amdgcn_mmac_f32_16x16x8f32(_a.f2[0], _b.f2[1], _d[1]); _d[2] = __builtin_amdgcn_mmac_f32_16x16x8f32(_a.f2[1], _b.f2[0], _d[2]); _d[3] = __builtin_amdgcn_mmac_f32_16x16x8f32(_a.f2[1], _b.f2[1], _d[3]); } ``` 在上面的代码里,我只用了一个`__sycnthreads()`来确保mma在lds之后进行,但是代码编译运行后出错,表现为:在不同的位置处,计算出错误的值,而这个错误的值每次运行都会变。很明显这是因为同步竞争。 查阅资料后我发现了`s_waitcnt lgkmcnt(0)`和`s_waitcnt vmcnt(0)`两条同步指令,在将我的同步方法换成用这两条指令后,同步竞争导致的错误消失了。 ```c++ #pragma unroll for (int r = 0; r < 2; r++) { int input_mma_load_offset = ((tid % 64) / 8 + r * 8) * 64 + (tid % 8) * 4; int input_lds_addr = input_mma_load_inner_offset + input_mma_load_offset; // DEBUG_PRINT("input_lds_addr: %d\n", input_lds_addr); input_lds_addr = input_lds_addr * sizeof(float); PREFETCH_LDS(_b, input_lds_addr); int weight_mma_load_offset = ((tid % 64) / 8 + r * 8) * 64 + (tid % 8) * 4; int weight_lds_addr = weight_mma_load_inner_offset + weight_mma_load_offset + weight_dsread_offset; weight_lds_addr = weight_lds_addr * sizeof(float); PREFETCH_LDS(_a, weight_lds_addr); asm volatile("s_waitcnt lgkmcnt(0)\n\t"); _d[0] = __builtin_amdgcn_mmac_f32_16x16x8f32(_a.f2[0], _b.f2[0], _d[0]); _d[1] = __builtin_amdgcn_mmac_f32_16x16x8f32(_a.f2[0], _b.f2[1], _d[1]); _d[2] = __builtin_amdgcn_mmac_f32_16x16x8f32(_a.f2[1], _b.f2[0], _d[2]); _d[3] = __builtin_amdgcn_mmac_f32_16x16x8f32(_a.f2[1], _b.f2[1], _d[3]); asm volatile("s_waitcnt vmcnt(0)\n\t"); __syncthreads(); } ``` 我的问题是:在使用`ds_read`和`mma`的时候,是否确如我所说需要使用`s_waitcnt lgkmcnt(0)`和`s_waitcnt vmcnt(0)`来进行同步而不能只使用`__sycnthreads()`?又是什么原因导致的?
全部评论(2)
只看楼主
A
ANYA
2楼
老师您好,全部用hip写的代码,ds_read mmac的等待不需要人为去加,编译器会去加上的,只需要在ds_write后加个同步,保证数据写道lds中;如果代码中使用内嵌汇编来处理lds/global相关的操作,那么等待指令需要自己人为的加上,编译器不会处理,global的读取需要vmcnt来等待,lds的读取需要lgkmcnt来等待
2025/9/11
周
周鑫
1楼
你好。 只看你的第一段代码看起来并没有什么问题,mmac等待ds_read指令结束开始运算。你可以尝试使用dccobjdump工具查看反编译的汇编代码确认这一点,编译器应该已经正确的插入了等待指令。 问题很可能出现在循环和外部代码的同步上。在你的第二段代码中,mmac后新增了同步的机制,这很有可能是实际缺失的同步指令。测试验证也很简单,同样使用第一段代码,只不过在mmac后加入__sycnthreads(),再验证下正确性看看。
2025/9/11
没有更多内容了
--
楼主
Level.3
0 帖子
楼主热帖
暂无数据