基于 Mali 600 gpu 的 OpenCL 指南,应使用 CL_MEM_ALLOC_HOST_PTR 删除任何数据副本并提高性能。
今天,我在具有 Mali 604 gpu 的 Arndale 板上使用 CL_MEM_ALLOC_HOST_PTR 测试内存复制时间。我用 CL_MEM_ALLOC_HOST_PTR 和 clEnqueueWriteBuffer 进行了测试。我发现,如果我使用 CL_MEM_ALLOC_HOST_PTR,总体上我并没有得到太多的性能提升。因为 clEnqueueMap 函数花费的时间几乎与 clEnqueueWriteBuffer 相同。这个测试是在向量加法上完成的。
我是如何测试的:我没有使用 malloc 创建指针并将数据传输到设备,而是首先使用 CL_MEM_ALLOC_HOST_PTR 创建了一个缓冲区。然后我使用 OpenCL API 映射了这个缓冲区。这返回一个指针,我用数据填充了这个指针指向的内存。这种情况下的映射机制需要时间。映射时间几乎等于 clENqueuewritebuffer。因此,从这个示例中,我没有使用 CL_MEM_ALLOC_HOST_PTR 获得任何显着改进。
我的问题是,当我使用 CL_MEM_ALLOC_HOST_PTR 时,为什么映射时间这么长?
这是性能测量:元素大小:10000000,内核:向量加法,所有时间都以微秒为单位
正常读写缓冲时间 缓冲区创建时间 20 入队写入缓冲时间 108019
CL_MEM_ALLOC_HOST_PTR - 在分配的缓冲区时间内直接复制数据 用数据填充 clEnqueueMap 返回的指针 208009 映射时间 81346 取消映射时间 269
CL_MEM_ALLOC_HOST_PTR - 使用 memcpy 将数据从 malloc 指针复制到主机分配指针 时间映射时间 64134 取消映射时间 190 memcpy 时间(将数据从已创建的 malloc 指针复制到主机分配的固定指针)
56987
这是我用于 Host_alloc_ptr 的代码片段:
start = getTime();
a_st=getTime();
bufferA = clCreateBuffer(context, CL_MEM_ALLOC_HOST_PTR, sizeof(cl_float) * ELE_NUM, NULL, &err);
cl_float* src_a=(cl_float*)clEnqueueMapBuffer(commandQueue, bufferA,CL_TRUE,CL_MAP_WRITE, 0, sizeof(cl_float) * ELE_NUM, 0, NULL, NULL, &err);
bufferB = clCreateBuffer(context, CL_MEM_ALLOC_HOST_PTR, sizeof(cl_float) * ELE_NUM, NULL, &err);
cl_float* src_b=(cl_float*)clEnqueueMapBuffer(commandQueue, bufferB,CL_TRUE,CL_MAP_WRITE, 0, sizeof(cl_float) * ELE_NUM, 0, NULL, NULL, &err);
clFinish(commandQueue);
a_en=getTime();
a_time=a_time+(a_en-a_st);
pfill_s=getTime();
for (int i = 0; i < ELE_NUM; i++){
src_a[i] = 100.0;
src_b[i] = 11.1;
}
pfill_e=getTime();
pfill_time=pfill_time+(pfill_e-pfill_s);
b_st=getTime();
clEnqueueUnmapMemObject(commandQueue, bufferB, src_b, 0, NULL, NULL);
clEnqueueUnmapMemObject(commandQueue, bufferA, src_a, 0, NULL, NULL);
clFinish(commandQueue);
b_en=getTime();
b_time=b_time+(b_en-b_st);
end = getTime();
creat_buffer += (end-start);
bufferC = clCreateBuffer(context, CL_MEM_ALLOC_HOST_PTR, sizeof(cl_float) * ELE_NUM, NULL, &err);