另一个答案很 危险!自己计算lane-id和warp-id。
#include <cuda.h>
#include <iostream>
inline __device__ unsigned get_lane_id() {
unsigned ret;
asm volatile("mov.u32 %0, %laneid;" : "=r"(ret));
return ret;
}
inline __device__ unsigned get_warp_id() {
unsigned ret;
asm volatile("mov.u32 %0, %warpid;" : "=r"(ret));
return ret;
}
__global__ void kernel() {
const int actual_warpid = get_warp_id();
const int actual_laneid = get_lane_id();
const int expected_warpid = threadIdx.x / 32;
const int expected_laneid = threadIdx.x % 32;
if (expected_laneid == 0) {
printf("[warp:] actual: %i expected: %i\n", actual_warpid,
expected_warpid);
printf("[lane:] actual: %i expected: %i\n", actual_laneid,
expected_laneid);
}
}
int main(int argc, char const *argv[]) {
dim3 grid(8, 7, 1);
dim3 block(4 * 32, 1);
kernel<<<grid, block>>>();
cudaDeviceSynchronize();
return 0;
}
这给出了类似的东西
[warp:] actual: 4 expected: 3
[warp:] actual: 10 expected: 0
[warp:] actual: 1 expected: 1
[warp:] actual: 12 expected: 1
[warp:] actual: 4 expected: 3
[warp:] actual: 0 expected: 0
[warp:] actual: 13 expected: 2
[warp:] actual: 12 expected: 1
[warp:] actual: 6 expected: 1
[warp:] actual: 6 expected: 1
[warp:] actual: 13 expected: 2
[warp:] actual: 10 expected: 0
[warp:] actual: 1 expected: 1
...
[lane:] actual: 0 expected: 0
[lane:] actual: 0 expected: 0
[lane:] actual: 0 expected: 0
[lane:] actual: 0 expected: 0
[lane:] actual: 0 expected: 0
[lane:] actual: 0 expected: 0
[lane:] actual: 0 expected: 0
[lane:] actual: 0 expected: 0
[lane:] actual: 0 expected: 0
[lane:] actual: 0 expected: 0
[lane:] actual: 0 expected: 0
另请参阅 PTX 文档
一个预定义的、只读的特殊寄存器,它返回线程的 warp 标识符。经线标识符在 CTA 内提供唯一经线编号,但不跨网格内的 CTA 提供。对于单个 warp 中的所有线程,warp 标识符将是相同的。
请注意,%warpid 是易失的,并在读取时返回线程的位置,但其值可能会在执行期间发生变化,例如,由于抢占后线程的重新调度。
因此,它是调度程序的 warp-id,但不能保证它与虚拟 warp-id 匹配(从 0 开始计数)。
文档说明了这一点:
出于这个原因,如果内核代码中需要这样的值,则应该使用 %ctaid 和 %tid 来计算虚拟扭曲索引;%warpid 主要用于启用分析和诊断代码来采样和记录工作场所映射和负载分布等信息。
如果你认为,好吧,让我们使用 CUB:这甚至会影响cub::WarpId()
返回调用线程的warp ID。Warp ID 保证在 warp 中是唯一的,但可能不对应于线程块内从零开始的排名。
编辑:使用%laneid
似乎是安全的。