在我的内核中,需要对一个只包含8个32位整数的小查找表进行大量的随机访问。每个内核都有一个唯一的查找表。以下是内核的简化版本,以说明如何使用查找表。
__kernel void some_kernel(
__global uint* global_table,
__global uint* X,
__global uint* Y) {
size_t gsi = get_global_size(0);
size_t gid = get_global_id(0);
__private uint LUT[8]; // 8 words of of global_table is copied to LUT
// Y is assigned a value from the lookup table based on the current value of X
for (size_t i = 0; i < n; i++) {
Y[i*gsi+gid] = LUT[X[i*gsi+gid]];
}
}
由于尺寸较小,将表保留在__private内存空间中可获得最佳性能。然而,由于查找表的访问方式是随机的,因此仍会存在大量性能损失。通过删除查找表代码(例如替换为简单算术运算),虽然内核会提供错误答案,但性能会提高三倍以上。
有更好的方法吗?我是否忽略了一些OpenCL功能,为非常小的内存块提供有效的随机访问?是否可以使用矢量类型实现高效解决方案?
【编辑】注意,X的最大值为7,但Y的最大值可达2 ^ 32-1。换句话说,查找表的所有比特位都被使用了,因此不能将其打包成更小的表示形式。
__constant
内存吗?GPU通常为常量内存实现单独的缓存和内存访问路径,以加速共享查找表等操作。 - user57368