0

私はCUDACを初めて使用し、slave_sort関数の次のコードを並列化しようとしています。これは、posixスレッドでの作業とすでに並列化されていることがわかります。次の構造体があります。

typedef struct{
   long densities[MAX_RADIX];
   long ranks[MAX_RADIX];
   char pad[PAGE_SIZE];
}prefix_node;

struct global_memory {
   long Index;                             /* process ID */
   struct prefix_node prefix_tree[2 * MAX_PROCESSORS];
} *global;

void slave_sort(){
         .
         .
         .
long *rank_me_mynum;
struct prefix_node* n;
struct prefix_node* r;
struct prefix_node* l;
         .
         .
MyNum = global->Index;
global->Index++;
n = &(global->prefix_tree[MyNum]);
     for (i = 0; i < radix; i++) {
        n->densities[i] = key_density[i];
        n->ranks[i] = rank_me_mynum[i];
     }
     offset = MyNum;
     level = number_of_processors >> 1;
     base = number_of_processors;
     while ((offset & 0x1) != 0) {
       offset >>= 1;
       r = n;
       l = n - 1;
       index = base + offset;
       n = &(global->prefix_tree[index]);
       if (offset != (level - 1)) {
         for (i = 0; i < radix; i++) {
           n->densities[i] = r->densities[i] + l->densities[i];
           n->ranks[i] = r->ranks[i] + l->ranks[i];
         }
       } else {
         for (i = 0; i < radix; i++) {
           n->densities[i] = r->densities[i] + l->densities[i];
         }
       }
       base += level;
       level >>= 1;
}

Mynumはプロセッサの数です。コードをカーネルに渡した後、Mynumを使用したいのrepresented by blockIdx.xですが、問題は構造体と混同されることです。それらをカーネルに渡す方法がわかりません。誰か助けてもらえますか?

次のコードは正しいですか?

__global__ void testkernel(prefix_node *prefix_tree, long *dev_rank_me_mynum, long *key_density,long radix)

int i = threadIdx.x + blockIdx.x*blockDimx.x;
prefix_node *n;
prefix_node *l;
prefix_node *r;
long offset;
     .
     .
     .
n = &prefix_tree[blockIdx.x];
if((i%numthreads) == 0){
    for(int j=0; j<radix; j++){
        n->densities[j] = key_density[j + radix*blockIdx.x];
        n->ranks[i] = dev_rank_me_mynum[j + radix*blockIdx.x];
    }
    .
    .
    .
 } 


int main(...){

    long *dev_rank_me_mynum;
    long *key_density;
    prefix_node *prefix_tree;
    long radix = 1024;

    cudaMalloc((void**)&dev_rank_me_mynum, radix*numblocks*sizeof(long));
    cudaMalloc((void**)&key_density, radix*numblocks*sizeof(long));
    cudaMalloc((void**)&prefix_tree, numblocks*sizeof(prefix_node));

    testkernel<<<numblocks,numthreads>>>(prefix_tree,dev_runk_me_mynum,key_density,radix);
}
4

1 に答える 1

0

編集で投稿したホスト API コードは正常に見えます。構造体には静的に宣言されたprefix_node配列のみが含まれているため、必要なのはcudaMalloc、カーネルが動作するメモリを割り当てるための単一の呼び出しだけです。prefix_treeカーネルに渡す方法も問題ありません。

カーネル コードは、不完全で明らかなタイプミスがいくつか含まれていますが、別の話です。の1つの「ノード」でブロックごとに1つのスレッドのみを動作させることを意図しているようですprefix_tree。これは非常に非効率的で、GPU の総容量のごく一部しか使用しません。たとえば、なぜこれを行うのですか:

prefix_node *n = &prefix_tree[blockIdx.x];
if((i%numthreads) == 0){
    for(int j=0; j<radix; j++){
        n->densities[j] = key_density[j + radix*blockIdx.x];
        n->ranks[j] = dev_rank_me_mynum[j + radix*blockIdx.x];
    }
    .
    .
    .
} 

あなたがこれにできるとき:

prefix_node *n = &prefix_tree[blockIdx.x];
for(int j=threadIdx.x; j<radix; j+=blockDim.x){
    n->densities[j] = key_density[j + radix*blockIdx.x];
    n->ranks[j] = dev_rank_me_mynum[j + radix*blockIdx.x];
}

これは、メモリを結合してブロック内のスレッドを 1 つだけではなく、実行するように選択した数だけ読み取り、使用するため、結果として何倍も高速になるはずです。したがって、投稿したシリアル C コードをカーネルに直接変換しようとする戦略を再考する必要があるかもしれません....

于 2012-06-04T09:18:05.933 に答える