我刚接触opencl,也许我要问一个愚蠢的问题!在
我在调整python/pyopencl
中的c/opencl
程序时遇到了一些问题。尤其是,我对列主和行主顺序的使用有点困惑。在
考虑到M[i,j]
,其Ni*Nj
维,则:
列主顺序定义为:i + Ni*j
行主顺序定义为:j + Nj*i
将此内核用于(3,3)
的本地大小:
__kernel void major(__global double local_i_i_major,
__global double local_j_i_major,
__global double local_i_j_major,
__global double local_j_j_major)
{
int i = get_global_id(0) ;
int j = get_global_id(1) ;
int Ni = get_num_groups(0) * get_local_size(0) ;
int Nj = get_num_groups(1) * get_local_size(1) ;
int main_i_major = j + i*Nj ;
int main_j_major = i + j*Ni ;
local_i_i_major(main_i_major) = get_local_id(0) ;
local_j_i_major(main_i_major) = get_local_id(1) ;
local_i_j_major(main_j_major) = get_local_id(0) ;
local_j_j_major(main_j_major) = get_local_id(1) ;
}
我们可以看看本地索引的分布情况。在
当使用列major时,我们得到:
^{pr2}$当我们使用Row major时,我们得到:
|-------------------------- (i,j) ----------------------|
_________________________________________________________
| (0,0) | (0,1) | (0,2) | (0,0) | (0,1) | ... |
| (1,0) | (1,1) | (1,2) | (1,0) | ... | ... |
| (2,0) | (2,1) | (2,2) | (2,0) | ... | ... |
| (0,0) | (0,1) | (0,2) | (0,0) | (0,1) | ... |
| (1,0) | (1,1) | (1,2) | (1,0) | ... | ... |
| (2,0) | (2,1) | (2,2) | (2,0) | ... | ... |
_________________________________________________________
当然,这些分布是不同的。特别是,我不了解本地索引分布情况下列的主要顺序。某些工作项似乎具有相同的id?有可能吗?在
当我读到有关C/openCL
的文章时,列主顺序在大多数时候被使用。当我阅读Python/PyOpencl
示例时,这是使用的行主顺序。在
考虑到Python和C都使用raw major顺序,为什么存在这种差异?在
还有,性能呢?使用列主键还是行主键顺序更好?在
是否可以更改opencl中值的排序方式?在
据我所知,如果您有C/OpenCL的列主有序内核(处理列连接到一个OpenCL缓冲区中),那么唯一的解决方案就是在行中有一些样本(由rowflux.append(样本)分析:
否则,您可以为numpy矩阵编写行主矩阵定向内核(当pyOpenCLcl.缓冲器从矩阵行连接逐个创建一个OpenCL缓冲行)。在
你混淆了内存布局和工作组维度的概念。OpenCL将工作空间的抽象细分定义为最多3个维度。它们不必与任何特定的内存布局相对应。最佳内存布局取决于您正在实现的特定算法。然而OpenCL并没有将工作项映射到内存,而是通过内存访问操作在内核中进行映射。在
OpenCL驱动程序将在逻辑上遍历工作组维度(因为它实际上是并行的),但是标准中没有指定顺序,因为它取决于体系结构。在一个工作组中,所有的工作项都可以被认为是并行执行的(尽管实际上,它们可能不是)。但即使它们也不代表一个特定的内存布局——例如,局部维度可能是(16,1),但您可以访问内存中的4x4区域。在
最佳映射取决于设备类型(GPU/FPGA vs CPU),因为它们的体系结构不同。在
总而言之,内存布局和逻辑维度(或域分解)这两个方面不能在一般情况下决定;它们取决于您正在实现的算法。在
您在使用特定内核时遇到的问题是因为您在无意义地混合逻辑索引,然后将它们用作物理索引。如果你一步一步地检查你的代码,你就会明白为什么在你的输出中有重复的条目。在
顺便说一句,你的代码看起来不像一个真正的内核——当然,参数应该是指针;然后用大括号()来访问它们,我想。在
相关问题 更多 >
编程相关推荐