CUDA a built-in variables comme threadIdx.x
et blockIdx.x
qui identifient chaque fil dans un bloc, et aussi qui bloquent ce fil est. Chaque thread dans un bloc aura la même valeur blockIdx.x
, mais chaque thread dans un bloc aura une valeur différente/unique (par bloc) threadIdx.x
.
Par conséquent, nous pouvons utiliser blockIdx.x
pour sélectionner une séquence spécifique pour chaque bloc. Cette variable peut être utilisée pour sélectionner la longueur de séquence correcte ainsi que le décalage pour chaque séquence/bloc.
Nous pouvons affecter un fil par bloc à chaque élément/caractère de séquence. Nous pouvons utiliser threadIdx.x
pour identifier, pour chaque thread, quel membre de séquence il doit sélectionner.
Voici un exemple bien travaillé:
$ cat t405.cu
#include <stdio.h>
__global__ void tk(char *seq, int *offsets, int *seq_lengths, int num_seq){
if (blockIdx.x < num_seq)
if (threadIdx.x < seq_lengths[blockIdx.x])
printf("block: %d, thread: %d, seq: %c\n", blockIdx.x, threadIdx.x, seq[offsets[blockIdx.x]+threadIdx.x]);
}
int main(){
char seq[] = {'a','b','f','g','c','d','>','b','g','d','>','a','b', 'c', 'd', 'e', '>'};
int seq_length[] = { 6, 3, 5 };
int offsets[] = { 0, 7, 11 };
int num_seq = 3;
int seq_sz = sizeof(seq);
int seq_l_sz = sizeof(seq_length);
int off_sz = sizeof(offsets);
char *d_seq;
int *d_seq_length, *d_offsets;
cudaMalloc(&d_seq, seq_sz);
cudaMalloc(&d_seq_length, seq_l_sz);
cudaMalloc(&d_offsets, off_sz);
cudaMemcpy(d_seq, seq, seq_sz, cudaMemcpyHostToDevice);
cudaMemcpy(d_seq_length, seq_length, seq_l_sz, cudaMemcpyHostToDevice);
cudaMemcpy(d_offsets, offsets, off_sz, cudaMemcpyHostToDevice);
tk<<<num_seq, 1024>>>(d_seq, d_offsets, d_seq_length, num_seq);
cudaDeviceSynchronize();
cudaError_t err = cudaGetLastError();
if (cudaSuccess != err) printf("cuda error: %s\n", cudaGetErrorString(err));
return 0;
}
$ nvcc -arch=sm_61 -o t405 t405.cu
$ ./t405
block: 1, thread: 0, seq: b
block: 1, thread: 1, seq: g
block: 1, thread: 2, seq: d
block: 2, thread: 0, seq: a
block: 2, thread: 1, seq: b
block: 2, thread: 2, seq: c
block: 2, thread: 3, seq: d
block: 2, thread: 4, seq: e
block: 0, thread: 0, seq: a
block: 0, thread: 1, seq: b
block: 0, thread: 2, seq: f
block: 0, thread: 3, seq: g
block: 0, thread: 4, seq: c
block: 0, thread: 5, seq: d
$
Si vous attendez plus de 1024 caractères dans une séquence, alors vous voulez modifier ce qui précède, peut-être d'avoir chaque thread gérer plusieurs caractères, peut-être dans un boucle.