Mi sono chiesto quale sarebbe stato il modo migliore per misurare le prestazioni (in flop) di un programma parallelo. Ho letto di papi_flops. Questo sembra funzionare bene per un programma seriale. Ma non so come posso misurare le prestazioni generali di un programma parallelo.Come misurare le prestazioni generali dei programmi paralleli (con papi)
Vorrei misurare le prestazioni di una funzione blas/lapack, nel mio esempio sotto gemm. Ma voglio anche misurare altre funzioni, specialmente funzioni in cui il numero di operazioni non è noto. (Nel caso di gemm gli op sono conosciuti (ops (gemm) = 2 * n^3), quindi potrei calcolare le prestazioni in funzione del numero di operazioni e del tempo di esecuzione.) La libreria (sto usando Intel MKL) genera automaticamente i fili. Quindi non posso misurare le prestazioni di ogni thread singolarmente e quindi ridurlo.
Questo è il mio esempio:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "mkl.h"
#include "omp.h"
#include "papi.h"
int main(int argc, char *argv[])
{
int i, j, l, k, n, m, idx, iter;
int mat, mat_min, mat_max;
int threads;
double *A, *B, *C;
double alpha =1.0, beta=0.0;
float rtime1, rtime2, ptime1, ptime2, mflops;
long long flpops;
#pragma omp parallel
{
#pragma omp master
threads = omp_get_num_threads();
}
if(argc < 4){
printf("pass me 3 arguments!\n");
return(-1);
}
else
{
mat_min = atoi(argv[1]);
mat_max = atoi(argv[2]);
iter = atoi(argv[3]);
}
m = mat_max; n = mat_max; k = mat_max;
printf (" Initializing data for matrix multiplication C=A*B for matrix \n"
" A(%ix%i) and matrix B(%ix%i)\n\n", m, k, k, n);
A = (double *) malloc(m*k * sizeof(double));
B = (double *) malloc(k*n * sizeof(double));
C = (double *) malloc(m*n * sizeof(double));
printf (" Intializing matrix data \n\n");
for (i = 0; i < (m*k); i++)
A[i] = (double)(i+1);
for (i = 0; i < (k*n); i++)
B[i] = (double)(-i-1);
memset(C,0,m*n*sizeof(double));
// actual meassurment
for(mat=mat_min;mat<=mat_max;mat+=5)
{
m = mat; n = mat; k = mat;
for(idx=-1; idx<iter; idx++){
PAPI_flops(&rtime1, &ptime1, &flpops, &mflops);
cblas_dgemm(CblasColMajor, CblasNoTrans, CblasNoTrans,
m, n, k, alpha, A, k, B, n, beta, C, n);
PAPI_flops(&rtime2, &ptime2, &flpops, &mflops);
}
printf("%d threads: %d in %f sec, %f MFLOPS\n",threads,mat,rtime2-rtime1,mflops);fflush(stdout);
}
printf("Done\n");fflush(stdout);
free(A);
free(B);
free(C);
return 0;
}
Questa è un'uscita (per dimensione della matrice 200):
1 threads: 200 in 0.001459 sec, 5570.258789 MFLOPS
2 threads: 200 in 0.000785 sec, 5254.993652 MFLOPS
4 threads: 200 in 0.000423 sec, 4919.640137 MFLOPS
8 threads: 200 in 0.000264 sec, 3894.036865 MFLOPS
Si osserva per il tempo di esecuzione, che le scale funzione GEMM. Ma il flop che sto misurando è solo la prestazione del thread 0.
La mia domanda è: come posso misurare le prestazioni complessive? Sono grato per qualsiasi input.
Umm .. Misurare i flop per ogni filo e quindi aggiungerli insieme? – Voo
Come posso fare questo? La libreria blas crea i thread. Quindi, la regione parallela si trova all'interno della funzione chiamata dgemm. Non ho accesso ai singoli thread. Ovviamente ho potuto ricompilare la libreria blas e quindi all'interno della regione parallela misurare le prestazioni per ogni thread (non è possibile nel caso di MKL, okay potrei passare a OpenBlas). Ma questo è quello che voglio evitare. – Sebastian
Potresti mostrare il numero di flop? Forse mflops è una media tra tutti i thread? –