从全局到本地内存的OpenCL复制字符

时间:2017-08-08 17:58:56

标签: c++ c opencl opencl-c

我在OpenCL技术中实施sha512。我有简单的内核函数定义

__kernel void _sha512(__global char *message, const uint length, __global char *hash);

在主机上我已经实现并成功测试了sha512算法的实现。

我将message数组中的数据复制到名为character的临时变量时出现问题。

char character = message[i];

i是一个循环变量 - 范围从0到消息的大小。

当我尝试在那里运行我的程序时,我遇到了这个错误

0x00007FFD9FA03D54 (0x0000000010CD0F88 0x0000000010CD0F88 0x0000000010BAEE88 0x000000001A2942A0), nvvmCompilerProperty() + 0x26174 bytes(s)
...
0x00007FFDDFA70D51 (0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000), RtlUserThreadStart() + 0x21 bytes(s)
0x00007FFDDFA70D51 (0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000), RtlUserThreadStart() + 0x21 bytes(s)

我对async_work_group_copy()感到厌烦,但我无法理解如何使用它 - 在文档中我无法找到任何示例代码。

我尝试使用char character = (__private char) message[i];,但它也没有用。

我不明白如何将最后一个参数传递到async_work_group_copy()以及如何使用它将数据从__global内存复制到__private内存。

1 个答案:

答案 0 :(得分:1)

默认情况下,OpenCL不允许在内核中进行单字节访问:内存访问需要是4个字节的倍数,与4字节边界对齐。如果您的实现支持它,您可以启用逐字节内存访问。这涉及cl_khr_byte_addressable_store extension,您需要在内核源代码中检查并明确启用它。试一试,看看它是否解决了你的问题。

要使用async_work_group_copy,请尝试以下操作:

#define LOCAL_MESSAGE_SIZE 64 // or some other suitable size for your workgroup
__local char local_message[LOCAL_MESSAGE_SIZE];
event_t local_message_ready = async_work_group_copy(local_message, message, LOCAL_MESSAGE_SIZE, 0);
// ...

// Just before you need to use local_message's content:
wait_group_events(1, &local_message_ready);
// Use local_message from here onwards

请注意,async_work_group_copy不是必需的;您可以直接访问全局内存。哪个更快取决于您的内核,OpenCL实现和硬件。

另一个选项(如果您的实现/硬件不支持cl_khr_byte_addressable_store,唯一的选择)是以至少4个字节的块为单位获取数据。将您的message声明为__global uint*并通过移动和屏蔽来解压缩字节:

uint word = message[i];
char byte0 = (word & 0xff);
char byte1 = ((word >> 8) & 0xff);
char byte2 = ((word >> 16) & 0xff);
char byte3 = ((word >> 24) & 0xff);
// use byte0..byte3 in your algorithm

根据实现,硬件等,您可能会发现这比按字节访问更快。 (如果您不确定所有部署平台是否都是小端的话,您可能需要check if you need to reverse the unpacking by reading the CL_DEVICE_ENDIAN_LITTLE property using clGetDeviceInfo。)