¿Cómo puedo verificar el progreso de la multiplicación de matrices?

Ahora solo necesito mostrar un progreso intermedio de la multiplicación de matrices.

for(unsigned int col=0; col<mtxSize; col++) { unsigned tmp = 0; for(unsigned int row=0; row<mtxSize; row++) { for(unsigned int idx=0; idx<mtxSize; idx++) { tmp += h_A[col*mtxSize+idx] * h_B[idx*mtxSize+row]; } h_Rs[col*mtxSize+row] = tmp; tmp = 0; int rate_tmp = (col*mtxSize + (row+1))*100; // Maybe like this... fprintf(stdout, "Progress : %d.%d %%\r", rate_tmp/actMtxSize, rate_tmp%actMtxSize); fflush(stdout); } } 

En el caso del código de host (use CPU), es muy fácil porque se procesa secuencialmente para que podamos verificar muy fácilmente.

Pero en el caso de la GPU que se procesa en paralelo, ¿qué debo hacer?

Una vez que el núcleo se está ejecutando, no regresa hasta que finalice la ejecución del kernel.

Así que no puedo verificar los datos intermedios durante el tiempo de ejecución del kernel.

Creo que necesito usar la llamada al kernel asincrónica, pero no sé bien.

E incluso si se utiliza la llamada al kernel asíncrona, para ver todos los datos en varios bloques sobre procesadores, ¿tengo que escribir la función atomicAdd () (en otras palabras, acceso a la memoria global) que incluye algunos gastos generales?

Dame algunos consejos o sugerencias.

Y quiero saber en el caso de CUDA.

Aquí hay un código que demuestra cómo verificar el progreso de un núcleo de matriz múltiple:

 #include  #include  #include  #define TIME_INC 100000000 #define INCS 10 #define USE_PROGRESS 1 #define MAT_DIMX 4000 #define MAT_DIMY MAT_DIMX #define cudaCheckErrors(msg) \ do { \ cudaError_t __err = cudaGetLastError(); \ if (__err != cudaSuccess) { \ fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \ msg, cudaGetErrorString(__err), \ __FILE__, __LINE__); \ fprintf(stderr, "*** FAILED - ABORTING\n"); \ exit(1); \ } \ } while (0) __global__ void mykernel(volatile int *data){ unsigned long time; for (int i = 0; i < INCS; i++){ atomicAdd((int *)data,1); __threadfence_system(); time = clock64(); while((clock64() - time)>>(d_data); cudaCheckErrors("kernel fail"); int value = 0; do{ int value1 = *h_data; if (value1 > value){ printf("h_data = %d\n", value1); value = value1;}} while (value < (INCS-1)); cudaDeviceSynchronize(); cudaCheckErrors("kernel fail 2"); // now try matrix multiply with progress float *h_c, *d_a, *d_b, *d_c; h_c = (float *)malloc(MAT_DIMX*MAT_DIMY*sizeof(float)); if (h_c == NULL) {printf("malloc fail\n"); return 1;} cudaMalloc((void **)&d_a, MAT_DIMX*MAT_DIMY*sizeof(float)); cudaCheckErrors("cudaMalloc a fail"); cudaMalloc((void **)&d_b, MAT_DIMX*MAT_DIMY*sizeof(float)); cudaCheckErrors("cudaMalloc b fail"); cudaMalloc((void **)&d_c, MAT_DIMX*MAT_DIMY*sizeof(float)); cudaCheckErrors("cudaMalloc c fail"); for (int i = 0; i < MAT_DIMX*MAT_DIMY; i++) h_c[i] = rand()/(float)RAND_MAX; cudaMemcpy(d_a, h_c, MAT_DIMX*MAT_DIMY*sizeof(float), cudaMemcpyHostToDevice); cudaCheckErrors("cudaMemcpy a fail"); cudaMemcpy(d_b, h_c, MAT_DIMX*MAT_DIMY*sizeof(float), cudaMemcpyHostToDevice); cudaCheckErrors("cudaMemcpy b fail"); cudaEvent_t start, stop; cudaEventCreate(&start); cudaEventCreate(&stop); *h_data=0; dim3 block(16,16); dim3 grid(((MAT_DIMX+block.x-1)/block.x), ((MAT_DIMY+block.y-1)/block.y)); printf("matrix multiply kernel starting\n"); cudaEventRecord(start); matmult<<>>(d_a, d_b, d_c, MAT_DIMY, MAT_DIMX, MAT_DIMX, d_data); cudaEventRecord(stop); #if USE_PROGRESS unsigned int num_blocks = grid.x*grid.y; float my_progress = 0.0f; value = 0; printf("Progress:\n"); do{ int value1 = *h_data; float kern_progress = (float)value1/(float)num_blocks; if ((kern_progress - my_progress)> 0.1f) { printf("percent complete = %2.1f\n", (kern_progress*100)); my_progress = kern_progress;}} while (my_progress < 0.9f); printf("\n"); #endif cudaEventSynchronize(stop); cudaCheckErrors("event sync fail"); float et; cudaEventElapsedTime(&et, start, stop); cudaCheckErrors("event elapsed time fail"); cudaDeviceSynchronize(); cudaCheckErrors("mat mult kernel fail"); printf("matrix multiply finished. elapsed time = %f milliseconds\n", et); return 0; } 

El código asociado con la primera llamada al núcleo es solo para demostrar la idea básica de tener un kernel que reporte su progreso.

La segunda parte del código muestra una muestra, multiplicación de matriz ingenua en la GPU, y la GPU informa que ha vuelto a su progreso. He incluido la posibilidad de eliminar el código de verificación de progreso a través de una macro de preprocesador, así como también la capacidad de medir el núcleo de la matriz de multiplicación. Para el caso que tengo aquí, no hubo una diferencia discernible en el tiempo con o sin el código de progreso. Entonces, aunque el código de informe de progreso probablemente agrega algo de sobrecarga, cuando se compara con el scope de un kernel de multiplicación de matriz de tamaño razonable, no agrega un tiempo significativo que pueda ver.