OpenCL如何更改cl_mem的内存地址?
我想做一个子矩阵乘法。假设我有一个函数:OpenCL如何更改cl_mem的内存地址?,opencl,matrix-multiplication,Opencl,Matrix Multiplication,我想做一个子矩阵乘法。假设我有一个函数: void MatMul(cl_mem A, cl_mem B, cl_mem C, int M, int K, int N) void ocl_push_array(cl_mem d_x, float *h_x, int n){ size_t data_size = sizeof(float)*n; err = clEnqueueWriteBuffer(queue, d_x, CL_TRUE, 0, data_size, h_x, 0,
void MatMul(cl_mem A, cl_mem B, cl_mem C, int M, int K, int N)
void ocl_push_array(cl_mem d_x, float *h_x, int n){
size_t data_size = sizeof(float)*n;
err = clEnqueueWriteBuffer(queue, d_x, CL_TRUE, 0, data_size, h_x, 0, NULL, NULL);
}
其中A是M*K,B是K*N,C是M*N,A、B、C都是通过主机内存float*h_A、*h_B、*hC通过以下函数传递的行主一维数组:
void MatMul(cl_mem A, cl_mem B, cl_mem C, int M, int K, int N)
void ocl_push_array(cl_mem d_x, float *h_x, int n){
size_t data_size = sizeof(float)*n;
err = clEnqueueWriteBuffer(queue, d_x, CL_TRUE, 0, data_size, h_x, 0, NULL, NULL);
}
我想问一下:
如果我想做子矩阵乘法,比如说逐行切片:
// cl_mem A, B, C;
for(int x=0; x<M; x+=16)
{
cl_mem A_sub = (cl_mem)((float *)A+x*K);
cl_mem C_sub = (cl_mem)((float *)C+x*N);
if((M-x+1)>=16)
MatMul(A_sub, B, C_sub, 16, K, N);
else
MatMul(A_sub, B, C_sub, M-x+1, K, N);
}
尺寸为:
#define BLOCK_SIZE 16
size_t localWorkSize[] = {BLOCK_SIZE, BLOCK_SIZE};
size_t globalWorkSize[] = {shrRoundUp(BLOCK_SIZE, N), shrRoundUp(BLOCK_SIZE, M)};
size_t shrRoundUp(int group_size, int global_size)
{
int r = global_size % group_size;
if(r == 0)
{
return global_size;
} else
{
return global_size + group_size - r;
}
}
该代码采用Nvidia OpenCL矩阵乘法示例。我的GPU是:英特尔(R)高清图形4600
谢谢 我认为你做不到:
cl_mem A_sub = (cl_mem)((float *)A+x*K);
因为cl_mem是OpenCL中的一个对象,它实际上是一个复杂的数据结构,而不仅仅是一个数据指针。它维护诸如指向实际内存的数据指针、对象引用、内存属性等信息。不同的运行时甚至可能有不同的cl_mem对象实现。这就是为什么会出现CL_INVALID_MEM_对象错误消息
要获得子矩阵的所需数据,可以执行以下操作之一:
定义两个新的cl_mem对象,并使用一个单独的内核
复印工作
使用clEnqueueCopyBuffer函数在主机上复制数据
代码域
使用CL_MEM_ALLOC_HOST_PTR到内存缓冲区,然后使用
ClenqueueEmapBuffer将GPU内存映射到主机内存指针,并
然后使用映射的主机内存修改内存内容
指针,完成后,取消映射指针以返回GPU内存
到设备内存域