我刚开始用OpenCL构建并行计算代码。
据我所知,从CPU端(主机)生成的数据通过缓冲区(clCreateBuffer -> clEnqueueWriteBuffer -> clSetKernelArg,然后由设备处理)进行传输。
我主要要处理的阵列(或矩阵)的大,双精度。
但是,我意识到,对于有错误的大于8000项的数组,代码永远不会运行。(这是有意义的,因为64 is等于8000倍的精度数字。)
错误码为-6 (CL_OUT_OF_HOST_MEMORY)或-31 (CL_INVALID_VALUE)。
还有一件事,当我将参数设置为二维数组时,我可以将大小设置为8000 x 8000。
到目前为止,我猜想对于一维数组来说,双精度的最大数据大小是8000 (64 2D ),但是我不知道2D或3D数组会发生什么。
发布于 2021-07-07 21:39:14
您可以在OpenCL中执行更大的数组,因为内存是可以保存的。例如,在CFD应用程序中,我通常使用20亿个浮动的线性4D阵列。
数组只需要一维;如果有2D或3D数组,则将它们线性化,例如,对于2D->1D坐标使用n=x+y*size_x。一些旧设备只允许设备内存大小的1/4数组。然而,现代设备通常对OpenCL规范有一个扩展,以启用更大的缓冲区。
下面是关于OpenCL C绑定的快速视图:
在您的例子中,有几个可能导致错误的原因:
。
为了给你一个更明确的答案,请提供一些更多的细节:
更新
我在您的代码中看到了一些错误:
clCreateBuffer和clEnqueueWriteBuffer中的length参数)需要数组a的字节数。如果a是double类型,那么这是a_length*sizeof(double),其中a_length是数组a中的元素数。sizeof(double)返回一个double数字的字节数,即8。因此,长度参数是数组中元素数的8字节。对于多个标志,|代替+。这里不应该是一个问题,但是unconvenional.0_8“作为缓冲区偏移量。这需要为零(0).const int a_length = 8000;
double* a = new double[a_length];
bfr(0) = clCreateBuffer(context, CL_MEM_READ_WRITE|CL_MEM_COPY_HOST_PTR, a_length*sizeof(double), c_loc(a), err);
if(err.ne.0) stop "Couldn't create a buffer";
err = clEnqueueWriteBuffer(queue, bfr(0), CL_TRUE, 0, a_length*sizeof(double), c_loc(a), 0, C_NULL_PTR, C_NULL_PTR);
err = clSetKernelArg(kernel, 0, sizeof(bfr(0)), C_LOC(bfr(0)));
print*, err;
if(err.ne.0) {
print *, "clSetKernelArg kernel"
print*, err
stop
}发布于 2021-07-12 09:56:38
我很感激你的好意。
我使用的硬件是特斯拉V100,它安装在我校的高性能计算机集群上。
下面是我正在测试数据传输的代码片段的一部分。
bfr(0) = clCreateBuffer(context,
& CL_MEM_READ_WRITE + CL_MEM_COPY_HOST_PTR,
& sizeof(a), c_loc(a), err);
if(err.ne.0) stop "Couldn't create a buffer";
err=clEnqueueWriteBuffer(queue,bfr(0),CL_TRUE,0_8,
& sizeof(a),c_loc(a),0,C_NULL_PTR,C_NULL_PTR)
err = clSetKernelArg(kernel, 0,
& sizeof(bfr(0)), C_LOC(bfr(0)))
print*, err
if(err.ne.0)then
print *, "clSetKernelArg kernel"
print*, err
stop
endif代码由Fortran使用clfortran模块构建。
再次感谢你的回答。
https://stackoverflow.com/questions/68292811
复制相似问题