san*_*age 5 gpgpu opencl gpu-programming
我在C中创建了以下结构"数据"
typedef struct data
{
double *dattr;
int d_id;
int bestCent;
}Data;
Run Code Online (Sandbox Code Playgroud)
'dattr'是上述结构中保持动态的数组.假设我必须创建10个以上结构的对象.即
dataNode = (Data *)malloc (sizeof(Data) * 10);
Run Code Online (Sandbox Code Playgroud)
对于这个结构的每个对象,我必须使用以下命令在C中为数组'dattr'重新分配内存:
for(i=0; i<10; i++)
dataNode[i].dattr = (double *)malloc(sizeof(double) * 3);
Run Code Online (Sandbox Code Playgroud)
如何在OpenCL中实现相同的功能?为结构对象分配内存后,如何为数组'dattr'分配内存?
必须使用clCreateBuffer(或clCreateImage2D/3D,如果您希望使用纹理内存)在主机线程中执行OpenCL设备(例如,GPU)中的内存分配.这些函数允许您自动将主机数据(例如使用malloc创建)复制到设备,但我通常更喜欢显式使用clEnqueueWriteBuffer/clEnqueueMapBuffer(如果使用纹理内存,则使用clEnqueueWriteImage/clEnqueueMapImage),以便我可以分析数据传输.这是一个例子:
#define DATA_SIZE 1000
typedef struct data {
cl_uint id;
cl_uint x;
cl_uint y;
} Data;
...
// Allocate data array in host
size_t dataSizeInBytes = DATA_SIZE * sizeof(Data);
DATA * dataArrayHost = (DATA *) malloc(dataSizeInBytes);
// Initialize data
...
// Create data array in device
cl_mem dataArrayDevice = clCreateBuffer(context, CL_MEM_READ_ONLY, dataSizeInBytes, NULL, &status );
// Copy data array to device
status = clEnqueueWriteBuffer(queue, dataArrayDevice, CL_TRUE, 0, dataSizeInBytes, &dataArrayHost, 0, NULL, NULL );
// Make sure to pass dataArrayDevice as kernel parameter
// Run kernel
...
Run Code Online (Sandbox Code Playgroud)
您需要考虑的是在执行OpenCL内核之前需要了解OpenCL内核的内存要求.因此,如果在内核执行之前(即在主机中)执行,则内存分配可以是动态的.没有什么可以阻止你多次调用内核,并且在每个时间调整(分配)内核内存需求.
考虑到这一点,我建议您重新考虑解决问题的方式.首先,使用结构数组比使用数组结构更简单(但不一定更有效)(在这种情况下,数组必须具有固定大小).
这只是为了让您了解OpenCL的工作原理.看看Khronos OpenCL资源页面,它有很多OpenCL教程和示例,以及Khronos OpenCL页面,其中包含官方OpenCL参考,手册页和快速参考卡.
正如 Faken 所建议的,如果您关心动态内存分配并且渴望稍微改变算法,这里有一些提示:
以下代码动态分配本地内存空间并将其作为第 8 个参数传递给 OpenCL 内核:
int N; //Number_of_data_points, which will keep on changing as per your requirement
size_t localMemSize = ( N* sizeof(int));
...
// Dynamically allocate local memory (allocated per workgroup)
clSetKernelArg(kernel, 8, localMemSize, NULL);
Run Code Online (Sandbox Code Playgroud)