ultima tutorial que programming parallel example developer c++ c cuda parallel-processing nvidia

c++ - tutorial - Cuda kernel regresando vectores



parallel programming cuda (1)

Tengo una lista de palabras, mi objetivo es hacer coincidir cada palabra en una frase muy larga. No tengo problemas para emparejar cada palabra, mi único problema es devolver un vector de estructuras que contenga información sobre cada coincidencia.

En codigo:

typedef struct { int A, B, C; } Match; __global__ void Find(veryLongPhrase * _phrase, Words * _word_list, vector<Match> * _matches) { int a, b, c; [...] //Parallel search for each word in the phrase if(match) //When an occurrence is found { _matches.push_back(new Match{ A = a, B = b, C = c }); //Here comes the unknown, what should I do here??? } } main() { [...] veryLongPhrase * myPhrase = "The quick brown fox jumps over the lazy dog etc etc etc..." Words * wordList = {"the", "lazy"}; vector<Match> * matches; //Obviously I can''t pass a vector to a kernel Find<<< X, Y >>>(myPhrase, wordList, matches); [...] }

He probado la biblioteca de Thrust pero sin éxito, ¿me pueden sugerir algún tipo de solución?

Muchas gracias.


algo como esto debería funcionar (codificado en el navegador, no probado):

// N is the maximum number of structs to insert #define N 10000 typedef struct { int A, B, C; } Match; __device__ Match dev_data[N]; __device__ int dev_count = 0; __device__ int my_push_back(Match * mt) { int insert_pt = atomicAdd(&dev_count, 1); if (insert_pt < N){ dev_data[insert_pt] = *mt; return insert_pt;} else return -1;} __global__ void Find(veryLongPhrase * _phrase, Words * _word_list, vector<Match> * _matches) { int a, b, c; [...] //Parallel search for each word in the phrase if(match) //When an occurrence is found { my_push_back(new Match{ A = a, B = b, C = c }); } } main() { [...] veryLongPhrase * myPhrase = "The quick brown fox jumps over the lazy dog etc etc etc..." Words * wordList = {"the", "lazy"}; Find<<< X, Y >>>(myPhrase, wordList); int dsize; cudaMemcpyFromSymbol(&dsize, dev_count, sizeof(int)); vector<Match> results(dsize); cudaMemcpyFromSymbol(&(results[0]), dev_data, dsize*sizeof(Match)); [...] }

Esto requerirá capacidad de cálculo 1.1 o superior para la operación atómica.

nvcc -arch=sm_11 ...

Aquí hay un ejemplo trabajado:

$ cat t347.cu #include <iostream> #include <vector> // N is the maximum number of structs to insert #define N 10000 typedef struct { int A, B, C; } Match; __device__ Match dev_data[N]; __device__ int dev_count = 0; __device__ int my_push_back(Match & mt) { int insert_pt = atomicAdd(&dev_count, 1); if (insert_pt < N){ dev_data[insert_pt] = mt; return insert_pt;} else return -1;} __global__ void Find() { if(threadIdx.x < 10) //Simulate a found occurrence { Match a = { .A = 1, .B = 2, .C = 3 }; my_push_back(a); } } main() { Find<<< 2, 256 >>>(); int dsize; cudaMemcpyFromSymbol(&dsize, dev_count, sizeof(int)); if (dsize >= N) {printf("overflow error/n"); return 1;} std::vector<Match> results(dsize); cudaMemcpyFromSymbol(&(results[0]), dev_data, dsize*sizeof(Match)); std::cout << "number of matches = " << dsize << std::endl; std::cout << "A = " << results[dsize-1].A << std:: endl; std::cout << "B = " << results[dsize-1].B << std:: endl; std::cout << "C = " << results[dsize-1].C << std:: endl; } $ nvcc -arch=sm_11 -o t347 t347.cu $ ./t347 number of matches = 20 A = 1 B = 2 C = 3 $

Tenga en cuenta que en este caso mi creación de estructura de resultado de Match es diferente, y estoy pasando por referencia, pero el concepto es el mismo.