【问题标题】:AMD clEnqueueMapBuffer and Pinned memoryAMD clEnqueueMapBuffer 和固定内存
【发布时间】:2017-09-11 14:01:06
【问题描述】:

我目前使用的是 AMD GPU。

/*device memory*/
pattern_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_char), NULL, &ret);
text_objA = clCreateBuffer(context, CL_MEM_READ_ONLY, fileLen * sizeof(char) / 2, NULL, &ret);
text_objB = clCreateBuffer(context, CL_MEM_READ_ONLY, fileLen * sizeof(char) / 2, NULL, &ret);
failure_obj = clCreateBuffer(context, CL_MEM_READ_ONLY, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_int), NULL, &ret);
ret_objA = clCreateBuffer(context, CL_MEM_WRITE_ONLY, MAX_PATTERN_NUM * sizeof(cl_int), NULL, &ret);
ret_objB = clCreateBuffer(context, CL_MEM_WRITE_ONLY, MAX_PATTERN_NUM * sizeof(cl_int), NULL, &ret);

/*pinned memory*/
mPattern_obj = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_char), NULL, &ret);
mText_obj = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, fileLen * sizeof(char), NULL, &ret);
mFailure_obj = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_int), NULL, &ret);
mRet_obj = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, MAX_PATTERN_NUM * sizeof(cl_int) * 2, NULL, &ret);

/*mapped pointer for pinned memory*/
pattern = (cl_char *)clEnqueueMapBuffer(command_queue[0], mPattern_obj, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_char), 0, NULL, NULL, &ret);
strings = (char *)clEnqueueMapBuffer(command_queue[0], mText_obj, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, fileLen * sizeof(char), 0, NULL, NULL, &ret);
failure = (cl_int *)clEnqueueMapBuffer(command_queue[0], mFailure_obj, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_int), 0, NULL, NULL, &ret);
matched = (cl_int *)clEnqueueMapBuffer(command_queue[0], mRet_obj, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, MAX_PATTERN_NUM * sizeof(cl_int) * 2, 0, NULL, NULL, &ret);

/*Initialize the mapped pointer*/

ret = clEnqueueWriteBuffer(command_queue[0], pattern_obj, CL_FALSE, 0, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_char), (void *)&pattern[0], 0, NULL, NULL);
ret = clEnqueueWriteBuffer(command_queue[0], text_objA, CL_FALSE, 0, halfSize, (void *)&strings[0], 0, NULL, NULL);
ret = clEnqueueWriteBuffer(command_queue[0], failure_obj, CL_FALSE, 0, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_int), (void *)&failure[0], 0, NULL, NULL);

ret = clEnqueueNDRangeKernel(command_queue[0], kernel[0], 1, NULL, &global_item_size, &local_item_size, 0, NULL, &kmp_event); 

clWaitForEvents(1, &kmp_event);

ret = clEnqueueWriteBuffer(command_queue[1], pattern_obj, CL_FALSE, 0, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_char), (void *)&pattern[0], 0, NULL, NULL);
ret = clEnqueueWriteBuffer(command_queue[1], text_objB, CL_FALSE, 0, halfSize, (void *)&strings[halfOffset], 0, NULL, NULL);
ret = clEnqueueWriteBuffer(command_queue[1], failure_obj, CL_FALSE, 0, MAX_PATTERN_SIZE * MAX_PATTERN_NUM * sizeof(cl_int), (void *)&failure[0], 0, NULL, NULL);

ret = clEnqueueNDRangeKernel(command_queue[1], kernel[1], 1, NULL, &global_item_size, &local_item_size, 0, NULL, &kmp_event);

clWaitForEvents(1, &kmp_event);

ret = clEnqueueReadBuffer(command_queue[0], ret_objA, CL_FALSE, 0, MAX_PATTERN_NUM * sizeof(cl_int), (void *)&matched[0], 0, NULL, NULL);

ret = clEnqueueReadBuffer(command_queue[1], ret_objB, CL_FALSE, 0, MAX_PATTERN_NUM * sizeof(cl_int), (void *)&matched[MAX_PATTERN_NUM], 0, NULL, NULL);

这是我的固定内存代码。

我使用 MapBuffer 和固定内存来重叠数据传输和执行。

我知道我的代码适用于 Nvidia GPU,但我认为 Nvidia 和 AMD 之间存在不匹配。

没有关于重叠传输和计算的 AMD GPU 示例代码。

所以,我不知道我必须做什么。

我应该进行哪些更改才能使我的代码在 AMD GPU 中运行?

我将 text_obj 划分为 A 和 B,因为我想通过将文本拆分为正面和背面来传输文本。

例如)文本:“ababcccc” text_objA=>abab 和 text_objB=>cccc

【问题讨论】:

    标签: asynchronous memory opencl gpu


    【解决方案1】:

    是的,NVIDIA 和 AMD 以不同的方式固定内存。 NVIDIA 有两个缓冲区(一个设备,一个主机)的奇怪要求,它神奇地检测到用于复制操作的主机指针是“特殊的”,这使得复制速度更快。请注意,在较新的驱动程序中,当您映射/取消映射设备缓冲区时,您可能会获得类似的性能。这也是 AMD 的做法(不需要两个缓冲区)。阅读 AMD 的开发者指南;他们有一整节关于内存传输的内容。底线:使用文档作为指导,但尝试一切并分析您的设备以找到真正有效的方法。

    【讨论】:

    • 谢谢!您的意思是,如果我尝试一些选项,是否也可以在 AMD 中重叠传输和执行?我看到一些 cmets 提到 AMD 不支持它。
    • 我认为某些 AMD 主板确实支持同时计算和传输;也许是 FirePro。请注意,某些 NVIDIA 主板具有双 DMA 引擎,您可以同时上传、计算和下载。您需要三个命令队列才能完成此任务。
    • 还有更多问题。 1)我对“下载”感到困惑。这是否意味着'clEnqueueReadBuffer()'? 2) 我参考了 AMD 优化指南并尝试了一些选项,但仍然无法正常工作。我使用一个缓冲区和两个命令队列是否正确? 3) 创建它们之后,我做了两次 setArg、writeBuffer 和 NDRangeKernel,以及两次 readBuffer。什么是错的? 4) 另外,在使用 writeBuffer 和 readBuffer 之后,我每次都放置 clEnqueueUnmapMemObject()。对吗?
    • 评论有很多问题。是的,“下载”意味着阅读。你需要一个命令队列来让每件事情重叠,并且 - 非常重要 - 使用事件来同步。我强烈建议首先使用单个命令队列让一切工作;多个队列是专家级的东西。 clEnqueueUnmapMemObject 和 writeBuffer/readBuffer 没有任何关系,除非你说的是 NVIDIA pinned memory,然后你可以等到你用完再取消映射。
    猜你喜欢
    • 2011-03-28
    • 2013-10-06
    • 2014-07-22
    • 2013-10-16
    • 2018-06-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-08
    • 2011-09-19
    相关资源
    最近更新 更多