Sto implementando la moltiplicazione C++ per matrici con diverse strutture dati e tecniche (vettori, matrici e OpenMP) e ho trovato una strana situazione ... La mia dinamica versione matrice è lavorare meglio:Perché la moltiplicazione C++ con array dinamico funziona meglio di std :: vector versione
volte:
OpenMP mult_1: tempo: 5,882 mila s
matrice mult_2: tempo: 1,478 mila s
mie flag di compilazione sono:
/usr/bin/g ++ -fopenmp -pthread -std = C++ 1A -O3
versione C++ vettore
typedef std::vector<std::vector<float>> matrix_f;
void mult_1 (const matrix_f & matrixOne, const matrix_f & matrixTwo, matrix_f & result) {
const int matrixSize = (int)result.size();
#pragma omp parallel for simd
for (int rowResult = 0; rowResult < matrixSize; ++rowResult) {
for (int colResult = 0; colResult < matrixSize; ++colResult) {
for (int k = 0; k < matrixSize; ++k) {
result[rowResult][colResult] += matrixOne[rowResult][k] * matrixTwo[k][colResult];
}
}
}
}
Versione array dinamico
void mult_2 (float * matrixOne, float * matrixTwo, float * result, int size) {
for (int row = 0; row < size; ++row) {
for (int col = 0; col < size; ++col) {
for (int k = 0; k < size; ++k) {
(*(result+(size*row)+col)) += (*(matrixOne+(size*row)+k)) * (*(matrixTwo+(size*k)+col));
}
}
}
}
prove:
C++ versione vettore
utils::ChronoTimer timer;
/* set Up simple matrix */
utils::matrix::matrix_f matr1 = std::vector<std::vector<float>>(size,std::vector<float>(size));
fillRandomMatrix(matr1);
utils::matrix::matrix_f matr2 = std::vector<std::vector<float>>(size,std::vector<float>(size));
fillRandomMatrix(matr2);
utils::matrix::matrix_f result = std::vector<std::vector<float>>(size,std::vector<float>(size));
timer.init();
utils::matrix::mult_1(matr1,matr2,result);
std::printf("openmp mult_1: time: %f ms\n",timer.now()/1000);
array dinamico versione
utils::ChronoTimer timer;
float *p_matr1 = new float[size*size];
float *p_matr2 = new float[size*size];
float *p_result = new float[size*size];
fillRandomMatrixArray(p_matr1,size);
fillRandomMatrixArray(p_matr2,size);
timer.init();
utils::matrix::mult_2(p_matr1,p_matr2,p_result,size);
std::printf("array mult_2: time: %f ms\n",timer.now()/1000);
delete [] p_matr1;
delete [] p_matr2;
delete [] p_result;
stavo controllando alcuni post precedenti, ma non riuscivo a trovare tutte le relative attività con il mio problema link, link2, link3:
UPDATE: Ho refactorized test con le risposte, e VectorWorks leggermente migliore:
vettore mult: tempo: 1,194 mila s
serie mult_2: tempo: 1,202 mila s
versione vettoriale C++
void mult (const std::vector<float> & matrixOne, const std::vector<float> & matrixTwo, std::vector<float> & result, int size) {
for (int row = 0; row < size; ++row) {
for (int col = 0; col < size; ++col) {
for (int k = 0; k <size; ++k) {
result[(size*row)+col] += matrixOne[(size*row)+k] * matrixTwo[(size*k)+col];
}
}
}
}
array dinamico versione
void mult_2 (float * matrixOne, float * matrixTwo, float * result, int size) {
for (int row = 0; row < size; ++row) {
for (int col = 0; col < size; ++col) {
for (int k = 0; k < size; ++k) {
(*(result+(size*row)+col)) += (*(matrixOne+(size*row)+k)) * (*(matrixTwo+(size*k)+col));
}
}
}
}
Inoltre, la versione vettorializzare funziona meglio (0,803 s);
I dati sono disposti in modo diverso nella memoria. Le matrici sono contigue nella memoria mentre si fa 'vector' assegna separatamente ciascun vettore. Se la dimensione è fissa in fase di compilazione, si può provare 'vector >' o fare qualcos'altro per assicurarsi che la matrice completa sia contigua nella memoria. –
PeterT
Vedere http://stackoverflow.com/questions/17259877/1d-or-2d-array-whats-faster sul motivo per cui in genere si desidera evitare strutture "reali" 2D (come 'T **', 'vector> '...) per la memorizzazione di matrici dense. –
Pixelchemist
Immagino che il layout della memoria non sia il tuo unico problema. Mostraci il tuo codice timer e quanti thread stai usando la versione openmp. – jepio