如何将字符串矩阵从C++传递到Cuda内核
How to pass string matrix to Cuda kernel from C++
问题:
我在C++中有一个矩阵,里面充满了字符串,我想把它传递给cuda内核函数。我知道CUDA不能处理字符串,所以经过一些研究,我尝试了下面列出的一些解决方案。
尝试次数:
-
在C++中定义一个指针数组,每个单元格包含一个指针字符(为了简单起见,tmp[i]用前面引用的矩阵中包含的字符串填充)
C++部分
char *tmp[3]; int text_length, array_length; text_length = 4; array_length = 3; tmp[0] = (char*) malloc(text_length*sizeof(char)); tmp[1] = (char*) malloc(text_length*sizeof(char)); tmp[2] = (char*) malloc(text_length*sizeof(char)); tmp[0] = "some"; tmp[1] = "rand"; tmp[2] = "text"; char *a[3]; for(int i=0;i<array_length;i++) { cudaMalloc((void**) &a[i],text_length*sizeof(char)); cudaMemcpy(&a[i],&tmp[i],text_length*sizeof(char),cudaMemcpyHostToDevice); } func<<<blocksPerGrid, threadsPerBlock>>>(a);
CUDA部分
__global__ void func(char* a[]){ for(int i=0;i<3;i++) printf("value[%d] = %s n",i, a[i]); }
输出
value[0] = (null) value[1] = (null) value[2] = (null)
-
将充满字符串的矩阵扩展到一个char指针,并将其传递给cuda内核,然后尝试检索字符串(再次在C++中简化代码)
C++部分
char *a; int index[6]; a = "somerandtext"; index[0] = 0; // first word start index[1] = 3; // first word end index[2] = 4; // same as first word index[3] = 7; index[4] = 8; index[5] = 1; func<<<blocksPerGrid, threadsPerBlock>>>(a,index);
CUDA部分
__global__ void func(char* a,int index[]){ int first_word_start = index[0]; int first_word_end = index[1]; // print first word for(int i=first_word_start;i<=first_word_end;i++) printf("%c",a[i]); }
输出
no output produced
我已经尝试了很多其他解决方案,但没有一个适合我……这个问题也可以重新提出,问:我如何将"n"个字符串传递到cuda内核,并在那里打印(和比较)所有字符串(请记住,我不能传递"n"变量)。
您所展示的代码中有许多是完整的,您遗漏的内容可能很重要。如果你展示了完整的代码,你会让其他人更容易帮助你。此外,每当你在使用CUDA代码时,最好使用正确的CUDA错误检查,这通常会让你发现哪些代码不起作用(我怀疑这可能有助于你的第二次尝试)。此外,使用cuda-memcheck
运行代码通常很有指导意义。
在第一次尝试中,您遇到了CUDA和嵌套指针的经典问题(a
是指向指针数组的指示器)。这个问题几乎在其他数据结构中隐藏指针的任何时候都会发生。将这样的数据结构从主机复制到设备需要"深度复制"操作,该操作有多个步骤。要了解更多信息,请搜索"CUDA 2D数组"(我认为规范答案是talonmies在这里给出的答案),或者在这里和这里查看我的答案。
还要注意的是,使用CUDA6,如果能够使用统一内存,"深度复制"在概念上对程序员来说会容易得多。
你的第二次尝试似乎是沿着一条"压平"你的2D或指向char
的ponter数组的指针的路径前进。这是深度复制"问题"的典型解决方案,可以降低代码复杂性,并可能提高性能。这里有一个完整的例子,融合了你第一次和第二次尝试的想法,这似乎对我有效:
$ cat t389.cu
#include <stdio.h>
__global__ void func(char* a, int *indexes, int num_strings){
for(int i=0;i<num_strings;i++){
printf("string[%d]: ", i);
for (int j=indexes[2*i]; j < indexes[2*i+1]; j++)
printf("%c", a[j]);
printf("n");
}
}
int main(){
int max_text_length, num_str;
num_str = 3;
char *tmp[num_str];
max_text_length = 12;
tmp[0] = (char*) malloc(max_text_length*sizeof(char));
tmp[1] = (char*) malloc(max_text_length*sizeof(char));
tmp[2] = (char*) malloc(max_text_length*sizeof(char));
tmp[0] = "some text";
tmp[1] = "rand txt";
tmp[2] = "text";
int stridx[2*num_str];
int *d_stridx;
stridx[0] = 0;
stridx[1] = 9;
stridx[2] = 9;
stridx[3] = 17;
stridx[4] = 17;
stridx[5] = 21;
char *a, *d_a;
a = (char *)malloc(num_str*max_text_length*sizeof(char));
//flatten
int subidx = 0;
for(int i=0;i<num_str;i++)
{
for (int j=stridx[2*i]; j<stridx[2*i+1]; j++)
a[j] = tmp[i][subidx++];
subidx = 0;
}
cudaMalloc((void**)&d_a,num_str*max_text_length*sizeof(char));
cudaMemcpy(d_a, a,num_str*max_text_length*sizeof(char),cudaMemcpyHostToDevice);
cudaMalloc((void**)&d_stridx,num_str*2*sizeof(int));
cudaMemcpy(d_stridx, stridx,2*num_str*sizeof(int),cudaMemcpyHostToDevice);
func<<<1,1>>>(d_a, d_stridx, num_str);
cudaDeviceSynchronize();
}
$ nvcc -arch=sm_20 -o t389 t389.cu
$ cuda-memcheck ./t389
========= CUDA-MEMCHECK
string[0]: some text
string[1]: rand txt
string[2]: text
========= ERROR SUMMARY: 0 errors
$
- CUDA内核和数学函数的显式命名空间
- 将 2D 推力::d evice_vector 复矩阵传递给 CUDA 内核函数
- 如何将矢量的数据传递给 CUDA 内核?
- 无法在 cuda 内核中使用我的模板类
- CUDA内核printf()在终端中不产生输出,在探查器中工作
- 编译为 cuda 内核调用提供了"expression must have integral or unscoped enum type"
- 使用模板模式优化 CUDA 内核
- 带有大结构变量的 CUDA 内核函数给出了错误的结果
- CUDA 内核在第二次运行时运行得更快 - 为什么?
- 在CUDA内核中传递一个常数整数
- 如何将函数作为CUDA内核参数传递
- 验证调用 cuda 内核的次数
- cuda 内核调用/传递参数中的编译错误
- 预期;在 CUDA 内核上
- CUDA 内核"Only a single pack parameter is allowed"解决方法?
- 降低CUDA内核运行时:内核中矩阵的动态内存分配
- 如何在多个 GPU 上同时执行 cufftXt 和 CUDA 内核
- 执行 CUDA 内核时黑屏C++输出正确的结果
- CUDA 内核中的竞争条件
- 优化三角矩阵计算的 CUDA 内核执行