opencl和pyopen中的Row和ColumnMajor

2024-06-06 03:19:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我刚接触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中值的排序方式?在


Tags: idget定义顺序mainlocalglobalint
2条回答

据我所知,如果您有C/OpenCL的列主有序内核(处理列连接到一个OpenCL缓冲区中),那么唯一的解决方案就是在行中有一些样本(由rowflux.append(样本)分析:

columnflux = np.transpose(np.asarray(rowflux, dtype=np.float64, order='F'))
...
_knl = mavg_k.yourcolumnorientedkernel
_knl.set_scalar_arg_dtypes([None,np.uint32,np.uint32,None])
_knl(queue,(globalSize,),(maxWorkGroupSize,),columnfluxbuffer,w,h,outputbuffer)

否则,您可以为numpy矩阵编写行主矩阵定向内核(当pyOpenCLcl.缓冲器从矩阵行连接逐个创建一个OpenCL缓冲行)。在

你混淆了内存布局和工作组维度的概念。OpenCL将工作空间的抽象细分定义为最多3个维度。它们不必与任何特定的内存布局相对应。最佳内存布局取决于您正在实现的特定算法。然而OpenCL并没有将工作项映射到内存,而是通过内存访问操作在内核中进行映射。在

OpenCL驱动程序将在逻辑上遍历工作组维度(因为它实际上是并行的),但是标准中没有指定顺序,因为它取决于体系结构。在一个工作组中,所有的工作项都可以被认为是并行执行的(尽管实际上,它们可能不是)。但即使它们也不代表一个特定的内存布局——例如,局部维度可能是(16,1),但您可以访问内存中的4x4区域。在

最佳映射取决于设备类型(GPU/FPGA vs CPU),因为它们的体系结构不同。在

总而言之,内存布局和逻辑维度(或域分解)这两个方面不能在一般情况下决定;它们取决于您正在实现的算法。在

您在使用特定内核时遇到的问题是因为您在无意义地混合逻辑索引,然后将它们用作物理索引。如果你一步一步地检查你的代码,你就会明白为什么在你的输出中有重复的条目。在

顺便说一句,你的代码看起来不像一个真正的内核——当然,参数应该是指针;然后用大括号()来访问它们,我想。在

相关问题 更多 >