2017-05-11 2 views
0

Ich muss eine multidimensionale Matrix von zufällig verteilten Zahlen mit einer Gauss-Verteilung erstellen und versuche, das Programm so optimiert wie möglich zu halten. Momentan verwende ich Boost-Matrizen, aber ich kann scheinbar nichts finden, was dies ohne manuelles Looping erreicht. Im Idealfall möchte ich etwas ähnlich der Python-Funktion numpy.random.randn(), aber das muss in C++ geschehen. Gibt es eine andere Möglichkeit, dies schneller als manuell zu erreichen?Erstellen Sie Matrix von Zufallszahlen in C++ ohne Schleife

+1

[Das klingt wie ein Job für 'std :: generate'!] (Http://en.cppreference.com/w/cpp/algorithm/generate) Aber ich bin mir nicht sicher, dass Sie viel Verbesserung sehen werden. – user4581301

+4

Warum ist die manuelle Schleife langsam? – Jarod42

+5

Ich würde vorschlagen, keine Sorgen über die Kosten des Schleifens und setzen Sie die Werte jedes Elements der Matrix einzeln. Ich vermute, dass Engpässe in Ihrem Programm woanders liegen. –

Antwort

0

Sie müssen sowieso eine Schleife, aber Sie können die Array-Lookup innerhalb Ihrer Schleife zu beseitigen. Die echte N-dimensionale Array-Indizierung wird teuer sein, daher ist die beste Option jede Bibliothek (oder Sie selbst), die Ihnen auch einen zugrunde liegenden linearen Datenspeicher zur Verfügung stellt.

Sie können dann das gesamte n-dimensionale Array so durchlaufen, als ob es linear wäre, und viele Multiplikationen der Indizes mit den Dimensionen vermeiden. Eine weitere Optimierung besteht darin, den Index ganz zu beseitigen, einen Zeiger auf das erste Element zu setzen und dann den Zeiger selbst zu iterieren, dies beseitigt eine ganze Variable in der CPU, die dem Compiler mehr Platz für andere Dinge geben kann . z.B. Wenn du 1000 Elemente in einem Vektor hast:

vector<int> data; 
data.resize(1000); 

int *intPtr = &data[0]; 
int *endPtr = &data[0] + 1000; 

while(intPtr != endPtr) 
{ 
    (*intPtr) == rand_function(); 
    ++intPtr; 
} 

Hier sind zwei Tricks passiert. Berechnen Sie die Endbedingung außerhalb der Schleife selbst (dies vermeidet das Nachschlagen einer Funktion wie vector :: size() 1000-mal) und arbeitet mit Zeigern zu den Daten im Speicher und nicht mit Indizes. Ein Index wird bei jedem Zugriff auf das Array intern in einen Zeiger umgewandelt. Durch Speichern des "aktuellen Zeigers" und jedesmal Hinzufügen von 1 werden die Kosten für die 1000-fache Berechnung der Zeiger aus den Indizes eliminiert.

Diese kann schneller sein, aber es hängt von der Implementierung ab. Compiler können einige der Handoptimierungen durchführen, aber nicht alle. Die rand_function sollte auch inline sein, um den Funktionsaufruf-Overhead zu vermeiden. Eine Warnung: Wenn Sie std :: vector mit dem Zeigertrick verwenden, dann ist es nicht Thread-sicher, wenn ein anderer Thread die Länge des Vektors während der Schleife änderte, dann kann der Vektor an einer anderen Stelle im Speicher neu zugeordnet werden. Führen Sie keine Pointertricks aus, es sei denn, Sie würden Ihre eigenen Vektor-, Array- und Tabellenklassen eigene nach Bedarf schreiben.

+0

Danke für die Erklärung! – nlhenderson17

Verwandte Themen