【发布时间】:2018-06-12 09:26:37
【问题描述】:
我正在尝试在 CUDA 中使用字符串数组(words)。
我尝试通过创建单个字符串来将其展平,但随后要对其进行索引,每次内核运行时我都必须对其进行一些处理。如果有 9000 个字长为 6 个字符,那么在最坏的情况下,我必须检查每个内核调用的 53994 个字符。所以我正在寻找不同的方法来做到这一点。
更新:忘了说,字符串的长度不同,所以我必须找到每个字符串的结尾。
接下来我尝试将每个单词复制到不同的内存位置,然后收集地址,并将其作为数组传递给 GPU,代码如下:
# np = numpy
wordList = ['asd','bsd','csd']
d_words = []
for word in wordList:
d_words.append(gpuarray.to_gpu(np.array(word, dtype=str)))
d_wordList = gpuarray.to_gpu(np.array([word.ptr for word in d_words], dtype=np.int32))
ker_test(d_wordList, block=(1,1,1), grid=(1,1,1))
在内核中:
__global__ void test(char** d_wordList) {
printf("First character of the first word is: %c \n", d_wordList[0][0]);
}
内核应该得到一个指向每个单词开头的 int32 指针数组,实际上是一个 char**(或 int**),但它并没有像我预期的那样工作。
这种方法有什么问题?
一般来说,在 PyCUDA(甚至在 CUDA)中处理字符串的“标准”方法是什么?
提前致谢。
【问题讨论】:
-
目前还不清楚为什么压扁字符串会导致算法困难。我称之为“标准”方法。也不清楚为什么您认为指针数组适合 int32 数组。您在使用 32 位操作系统吗?
-
忘了提到字符串的长度不同,所以我必须检查每个字符是否是每个“索引”的字符串结尾。这看起来很乏味,写起来也可能计算起来。所以第二种方法会更容易使用,但我不知道它会产生什么性能差异。啊,int32 可能是个问题,出于某种原因认为它就足够了。
-
除了传递字符串的压缩数组外,还要传递每个字符串的起始偏移量(不是指针)的压缩数组。在打包字符串时应该很容易组装,并且应该很容易传递(作为 int32 数组),并且应该很容易(并且更有效)使用它在 CUDA 内核中进行基于指针的访问本身,而不是使用您在此处讨论的双指针方法。每个字符串的长度只是一个索引/偏移量与下一个索引/偏移量之间的差异。
-
谢谢!指针大小确实是问题所在,我不知道为什么我认为内存地址是 32 位。传递数组偏移量的想法看起来也很方便,我也应该考虑一下。所以现在我有两个选项可供选择,所有问题都解决了。我不想删除这个问题,但万一有人遇到类似的问题,所以如果你发布一个答案,那么我可以正确地“关闭”它。
-
正确地说,您应该使用
numpy.uintp作为指针的 dtype。 PyCUDA 在内部就是这样做的
标签: python arrays string cuda pycuda