Après this question en référence au shared memory example dans le guide officiel, je suis en train de construire la matrice de l'équation de la chaleur, ce qui est tout comme dans cette image mal dessiné j'ai faitmatrice équation de la chaleur dans CUDA - adresse illégale erreur
Voici ce que je l'ai fait jusqu'à présent, par exemple un minimum
#define N 32
#define BLOCK_SIZE 16
#define NUM_BLOCKS ((N + BLOCK_SIZE - 1)/ BLOCK_SIZE)
__global__ void heat_matrix(int* A)
{
const unsigned int tid = threadIdx.x + blockIdx.x * blockDim.x;
__shared__ int temp_sm_A[N*N];
int* temp_A = &temp_sm_A[0]; memset(temp_A, 0, N*N*sizeof(int));
if (tid < N) //(*)
{
#pragma unroll
for (unsigned int m = 0; m < NUM_BLOCKS; ++m)
{
#pragma unroll
for (unsigned int e = 0; e < BLOCK_SIZE ; ++e)
{
if ((tid == 0 && e == 0) || (tid == (N-1) && e == (BLOCK_SIZE-1)))
{
temp_A[tid + (e + BLOCK_SIZE * m) * N] = -2;
temp_A[tid + (e + BLOCK_SIZE * m) * N + (tid==0 ? 1 : -1)] = 1;
}
if (tid == e)
{
temp_A[tid + (e + BLOCK_SIZE * m) * N - 1] = 1;
//printf("temp_A[%d] = 1;\n", (tid + (e + BLOCK_SIZE * m) * N -1));
temp_A[tid + (e + BLOCK_SIZE * m) * N] = -2;
//printf("temp_A[%d] = -2;\n", (tid + (e + BLOCK_SIZE * m) * N));
temp_A[tid + (e + BLOCK_SIZE * m) * N + 1] = 1;
//printf("temp_A[%d] = 1;\n", (tid + (e + BLOCK_SIZE * m) * N +1));
}
}
}
__syncthreads(); //(**)
memcpy(A, temp_A, N*N*sizeof(int));
}
}
int main(){
int* h_A = (int*)malloc(N*N*sizeof(int)); memset(h_A, 0, N*N*sizeof(int));
int* d_A;
checkCudaErrors(cudaMalloc((void**)&d_A, N*N*sizeof(int)));
checkCudaErrors(cudaMemcpy(d_A, h_A, N*N*sizeof(int), cudaMemcpyHostToDevice));
dim3 dim_grid((N/2 + BLOCK_SIZE -1)/ BLOCK_SIZE);
dim3 dim_block(BLOCK_SIZE);
heat_matrix <<< dim_grid, dim_block >>> (d_A);
checkCudaErrors(cudaMemcpy(h_A, d_A, N*N*sizeof(int), cudaMemcpyDeviceToHost));
...
}
Le code est conçu pour convenir à un grand N (supérieur à 32). J'ai profité de la division en blocs. Lors de l'exécution nvcc
donne
CUDA error at matrix.cu:102 code=77(cudaErrorIllegalAddress) "cudaMemcpy(h_A, d_A, N*N*sizeof(int), cudaMemcpyDeviceToHost)"
Et cuda-memcheck
ne fournit qu'une seule erreur (en fait il y a un autre, mais il vient de cudasuccess=checkCudaErrors(cudaDeviceReset()); ...
)
========= CUDA-MEMCHECK
========= Invalid __shared__ write of size 4
========= at 0x00000cd0 in heat_matrix(int*)
========= by thread (0,0,0) in block (0,0,0)
========= Address 0xfffffffc is out of bounds
...
Je ne vois pas où je fait de mal dans le code. Comment le fil 0
dans le premier bloc peut-il provoquer un accès illégal? Il y a même le cas spécifique if
à traiter, et la ligne du code dans lequel l'erreur s'est produite n'est pas signalée.
De plus, y a-t-il un moyen plus efficace pour mon code que de traiter tous ces if
s? Bien sûr il y a, mais je ne pouvais pas trouver une meilleure expression parallèle pour diviser les cas dans le second for
.
Sur une note de côté, pour moi le (*)
semble inutile; au lieu (**)
est nécessaire si je veux suivre avec d'autres appels de fonction GPU. Ai-je raison?
Très bien! D'abord, je vais effacer les 'memcpy' et' memset'. Alors, devrais-je séparer les fils entre travailler dans le "milieu" de la matrice et dans les limites (disons, avec 'if (tid == 0)' et similaires)? OK à propos des déformations, ce ne sont que des valeurs appropriées pour jeter un coup d'œil à la sortie dans l'invite – Eugenio
Vous n'avez pas besoin de considérer les bordures explicitement. Vérifiez si vous êtes en diagonale, sur les éléments voisins ou ailleurs. – tera
Votre modification a été très utile. C'était l'affaire, merci – Eugenio