2012-03-30 7 views
2

Ich führe gerade einen Algorithmus, der sehr schwer aber extrem parallel ist.OpenMP und Optimieren von Vektoroperationen

Ich habe nach Möglichkeiten gesucht, um es zu beschleunigen, und ich habe festgestellt, dass die langsamste Operation, die ich habe, ist meine VecAdd-Funktion (Es wird Tausende Male auf einem 6000 oder so breiten Vektor aufgerufen).

bool VecAdd(float* pOut, const float* pIn1, const float* pIn2, unsigned int num) 
{ 
    for(int idx = 0; idx < num; idx++) 
    { 
     pOut[idx] = pIn1[idx] + pIn2[idx]; 
    } 
    return true; 
} 

Es ist eine sehr einfache Schleife aber alle Ergänzungen können parallel durchgeführt werden:

Es wird wie folgt realisiert. Meine erste Optimierungsmöglichkeit besteht darin, zur Verwendung von SIMD überzugehen, da ich dabei leicht eine fast 4-fache Geschwindigkeit erreichen kann.

Ich bin aber auch an der Möglichkeit interessiert, OpenMP zu verwenden und automatisch die for-Schleife zu fädeln (was mir möglicherweise eine weitere 4x-Beschleunigung für insgesamt 16x mit SIMD gibt).

Allerdings läuft es wirklich langsam. Wenn die Schleife gerade ist, dauert es etwa 3,2 Sekunden, um meine Beispieldaten zu verarbeiten. Wenn ich

vor der for-Schleife einfügte, nahm ich an, dass es mehrere Blöcke von Additionen zu anderen Threads auslagern würde.

Leider dauert es ca. 7 Sekunden, um meine Beispieldaten zu verarbeiten.

Jetzt verstehe ich, dass viele meiner Probleme hier durch Overheads mit der Einrichtung von Threads und so weiter verursacht werden, aber ich bin immer noch überrascht, wie viel langsamer es Dinge laufen lässt.

Ist es möglich, dies zu beschleunigen, indem Sie den Thread-Pool im Voraus einrichten, oder kann ich diese Gemeinkosten nie bekämpfen?

Irgendwelche Gedanken auf dem Rat, ob ich das schön mit OpenMP einfädeln kann, werden sehr geschätzt!

+0

Gemeinsame OpenMP-Implementierungen werden im Voraus einen Thread-Pool einrichten. –

+1

Nur um sicher zu sein, da es in Ihrer Frage nirgends erwähnt wird: Sie haben einen Kern für jeden Thread, nicht wahr? –

+0

Es sieht nicht wie ein Cache-Problem aus, da jedes Array nur 6000 Floats ist. Welche OpenMP-Implementierung verwenden Sie? – devil

Antwort

4

Ihre Schleife sollte parallel mit dem #pragma omp parallel für. Allerdings denke ich, das Problem ist, dass Sie auf dieser Ebene nicht parallelisieren sollten. Sie haben gesagt, dass die Funktion tausende Male aufgerufen wird, aber nur auf 6000 Floats funktioniert. Parallelisieren auf der höheren Ebene, so dass jeder Thread für tansansands/4 Aufrufe an VecAdd verantwortlich ist. Gerade jetzt haben Sie diesen Algorithmus:

  1. Liste item
  2. serielle Ausführung
  3. (re) Threads beginnen
  4. kurze Rechen
  5. Threads synchronisieren (am Ende der for-Schleife)
  6. zurück zur Seriennummer

Ändern Sie es so, dass es parallel am höchsten po ist ssible Ebene.

Speicherbandbreite natürlich wichtig, aber es gibt keine Möglichkeit, dass es langsamer als serielle Ausführung führen würde.

+0

Das ist so ziemlich wie ich vermutete. Prost! :) – Goz