2016-06-09 15 views
0

Ich hatte Probleme bei der Generierung von Zufallszahlen über mehrere Threads. Dies war der Grund für die Verwendung der gleichen Random-Engine für alle Threads. Dann habe ich einen Vektor implementiert, der für jeden Thread eine zufällige Engine enthält (fand diese Lösung in einem anderen Post hier im Stackoverflow). Aber ich würde erwarten, dass die Anzahl der Iterationen pro Sekunde linear mit der Anzahl der Threads wächst, die ich ausführe. Aber das scheint nicht der Fall zu sein.Engpass bei der Zufallsgenerierung mit mehreren Threads

Hier ist ein minimales Beispiel:

#include <random> 
#include <omp.h> 

const int threads = 4; 

int main() 
{ 
    std::uniform_int_distribution<uint64_t> uint_dist; 
    std::vector<std::mt19937_64> random_engines; 
    std::random_device rd; 

    for (int i = 0;i < threads;i++) 
     random_engines.push_back(std::mt19937_64((rd()))); 

    omp_set_num_threads(threads); 

    int counter = 0; 
    #pragma omp parallel for 
    for (int i = 0;i < threads;++i) 
    { 
     int thread = omp_get_thread_num(); 
     while (counter < 100) 
     { 
      if (uint_dist((random_engines[thread])) < (1ULL << 42)) 
       counter++; 
     } 
    } 
} 

Während diesen Code mit einem aktiven Thread ausgeführt wird es eine durchschnittliche Ausführungszeit von ca. 4 Sekunden auf meiner CPU nimmt. Wenn ich Threads auf 4 setze, ergibt sich eine durchschnittliche Ausführungszeit von ~ 2 Sekunden, also erhält die Anzahl der Threads einen Multiplikator von 4, was zu einer Beschleunigung von 2 führt. Vermisse ich etwas?

+1

Es gibt ein mögliches Problem mit der Synchronisierung für 'Counter': entweder Threads blockieren einander, oder lesen-ändern-schreiben ist nicht atomar und einige Schreibvorgänge sind routinemäßig verloren. Ich kenne OpenMP nicht genug, um zu sagen, was wahrscheinlicher ist. –

Antwort

1

Erstens, wenn Sie zwei Kerne und Hyper Threading haben, sieht es aus wie vier Prozessoren zu Ihrem Code, aber es ist nicht vier Mal die Geschwindigkeit, nur ein bisschen besser als doppelt so schnell, wenn Sie Glück haben.

Zweitens, wenn Sie alle CPU-Leistung, die Sie haben, verwenden, wird Ihr Computer aufheizen und dann die Taktfrequenz verringern.

Drittens verwenden Sie möglicherweise eine Zufallszahl mit großem Status. Der Zustand für einen kann in den L1-Cache passen, aber nicht für vier von ihnen. Das kann zu einer großen Verlangsamung führen.

Viertens haben Sie eine Variable "counter", die zwischen Threads geteilt und bei jeder Iteration gelesen wird. Das wird nicht schnell sein.