Ho estratto questa semplice funzione membro da un programma 2D più grande, tutto ciò che fa è un ciclo per accedere da tre array diversi e fare un'operazione matematica (convoluzione 1D). Ho testato con l'utilizzo di OpenMP per rendere questa particolare funzione più veloce:Perché questo ciclo non è più veloce con OpenMP?
void Image::convolve_lines()
{
const int *ptr0 = tmp_bufs[0];
const int *ptr1 = tmp_bufs[1];
const int *ptr2 = tmp_bufs[2];
const int width = Width;
#pragma omp parallel for
for (int x = 0; x < width; ++x)
{
const int sum = 0
+ 1 * ptr0[x]
+ 2 * ptr1[x]
+ 1 * ptr2[x];
output[x] = sum;
}
}
Se uso gcc 4.7 su Debian/amd64 ansimante il programma globale esegue molto più lento su una macchina 8 CPU. Se utilizzo gcc 4.9 su un debian/jessie amd64 (solo 4 CPU su questa macchina) il programma complessivo funziona con una differenza minima.
Utilizzo time
confrontare: singola corsa nucleo:
$ ./test black.pgm out.pgm 94.28s user 6.20s system 84% cpu 1:58.56 total
più run nucleo:
$ ./test black.pgm out.pgm 400.49s user 6.73s system 344% cpu 1:58.31 total
Dove:
$ head -3 black.pgm
P5
65536 65536
255
Così Width
è impostato 65536
durante l'esecuzione.
Se resto, sto usando cmake per la compilazione:
add_executable(test test.cxx)
set_target_properties(test PROPERTIES COMPILE_FLAGS "-fopenmp" LINK_FLAGS "-fopenmp")
E CMAKE_BUILD_TYPE è impostata su:
CMAKE_BUILD_TYPE:STRING=Release
che implica -O3 -DNDEBUG
La mia domanda, perché è questo ciclo for
non più veloce usando multi-core? Non c'è alcuna sovrapposizione nell'array, l'openmp dovrebbe dividere equamente la memoria. Non vedo da dove viene il collo di bottiglia?
Edit: Come è stato commentato, ho cambiato la mia file di input in:
$ head -3 black2.pgm
P5
33554432 128
255
Così Width
è ora impostata durante l'esecuzione 33554432
(deve essere considerato da abbastanza). Ora la temporizzazione rivela:
singola corsa nucleo:
$ ./test ./black2.pgm out.pgm 100.55s user 5.77s system 83% cpu 2:06.86 total
Multi run nucleo (per qualche motivo CPU% sia sempre inferiore al 100%, che indicherebbe filetti affatto):
$ ./test ./black2.pgm out.pgm 117.94s user 7.94s system 98% cpu 2:07.63 total
in generale, falso conflitto di condivisione/blocco. Inoltre, quanto è grande la larghezza? – sehe
@se dispiace mi sono dimenticato di dirlo. – malat
Come l'hai provato? Dubito che il singolo loop da 64k che hai dato richieda così tanto tempo. – ElderBug