Dies ist eine Fortsetzung von Wie langsam ist Python wirklich? (Oder wie schnell ist Ihre Sprache?) .
Es stellte sich heraus, dass es ein bisschen zu einfach war, für meine letzte Frage ein x100-Speedup zu bekommen. Für diejenigen, die die Herausforderung genossen haben, aber etwas Schwierigeres wollen, bei dem sie ihre geringen Fähigkeiten wirklich einsetzen können, ist hier Teil II. Die Herausforderung besteht darin, eine x100-Beschleunigung für den folgenden Python-Code zu erhalten, der auf meinem Computer getestet wurde.
Um es schwieriger zu machen, verwende ich diesmal Pypy. Das aktuelle Timing für mich ist 1 Minute und 7 Sekunden mit Pypy 2.2.1.
Regeln
- Die erste Person, die Code einreicht, den ich ausführen kann, der korrekt ist und der auf meinem Computer 100-mal schneller ist, erhält eine Prämie von 50 Punkten.
- Ich werde den Gewinn nach einer Woche an den schnellsten Code vergeben.
import itertools
import operator
import random
n = 8
m = 8
iters = 1000
# creates an array of 0s with length m
# [0, 0, 0, 0, 0, 0, 0, 0]
leadingzerocounts = [0]*m
# itertools.product creates an array of all possible combinations of the
# args passed to it.
#
# Ex:
# itertools.product("ABCD", "xy") --> Ax Ay Bx By Cx Cy Dx Dy
# itertools.product("AB", repeat=5) --> [
# ('A', 'A', 'A', 'A', 'A'),
# ('A', 'A', 'A', 'A', 'B'),
# ('A', 'A', 'A', 'B', 'A'),
# ('A', 'A', 'A', 'B', 'B'),
# etc.
# ]
for S in itertools.product([-1,1], repeat = n+m-1):
for i in xrange(iters):
F = [random.choice([-1,0,0,1]) for j in xrange(n)]
# if the array is made up of only zeros keep recreating it until
# there is at least one nonzero value.
while not any(F):
F = [random.choice([-1,0,0,1]) for j in xrange(n)]
j = 0
while (j < m and sum(map(operator.mul, F, S[j:j+n])) == 0):
leadingzerocounts[j] +=1
j += 1
print leadingzerocounts
Die Ausgabe sollte ähnlich sein
[6335185, 2526840, 1041967, 439735, 193391, 87083, 40635, 19694]
Sie müssen einen zufälligen Startwert in Ihrem Code verwenden, und jeder Zufallszahlengenerator, der gut genug ist, um Antworten in der Nähe der oben genannten zu geben, wird akzeptiert.
Mein Computer Die Timings werden auf meinem Computer ausgeführt. Dies ist eine Ubuntu-Standardinstallation auf einem AMD FX-8350 Eight-Core-Prozessor. Dies bedeutet auch, dass ich in der Lage sein muss, Ihren Code auszuführen.
Erklärung des Codes
Dieser Code durchläuft alle Arrays S der Länge n + m-1, die sich aus -1s und 1s zusammensetzen. Für jedes Array S werden 1000 von Null verschiedene zufällige Arrays F der Länge n abgetastet, die aus -1,0 oder 1 bestehen, mit einer Wahrscheinlichkeit von 1/4, 1/2, / 14, jeden Wert zu nehmen. Dann berechnet es die inneren Produkte zwischen F und jedem Fenster von S der Länge n, bis es ein inneres Produkt ungleich Null findet. Es addiert 1 zu leadingzerocounts
jeder Position, an der es ein inneres Produkt von Null gefunden hat.
Status
Perl . 2,7-fache Verlangsamung durch @tobyink. (Im Vergleich zu Pypy nicht Cpython.)
J . 39-fache Beschleunigung durch @Eelvex.
- C . 59-fache Beschleunigung durch @ace.
- Julia . 197-mal schneller, ohne Startzeit von @ one-more-minute. 8,5-fache Geschwindigkeit einschließlich Startzeit (in diesem Fall sind 4 Prozessoren schneller als 8).
- Fortran . 438-fache Beschleunigung durch @ semi-extrinsic.
- Rpython . 258-fache Beschleunigung durch @primo.
- C ++ . 508-fache Beschleunigung durch @ilmale.
(Ich habe aufgehört, die neuen Verbesserungen zeitlich festzulegen, weil sie zu schnell und die Iterationen zu klein waren.)
Es wurde darauf hingewiesen, dass Timings unter einer Sekunde unzuverlässig sind und auch einige Sprachen Startkosten verursachen. Das Argument ist, dass, wenn Sie einschließen möchten, Sie auch die Kompilierungszeit von C / C ++ usw. einschließen sollten. Hier sind die Zeiten für den schnellsten Code mit der Anzahl der Iterationen, die auf 100.000 erhöht wurden.
- Julia . 42 Sekunden von @ one-more-minute.
- C ++ . 14 Sekunden von @GuySirton.
- Fortran . 14s von @ semi-extrinsic.
- C ++ . 12s von @ilmale.
- Rpython . 18s von @primo.
- C ++ . 5s von @Stefan.
Der Gewinner ist .. Stefan!
Follow-up-Challenge veröffentlicht. Wie hoch kannst du gehen? (Eine Codierung + Algorithmen Herausforderung) . Dieser ist schwieriger.
quelle
Antworten:
C ++ bisschen Magie
~ 16 ms Multithreading, 56 ms Singlethreading. ~ 4000 Beschleunigung.
(Die Beschleunigung basiert auf Multithread-Code auf meinem i7-2820QM und den in der Frage genannten 1 min 9 Sekunden. Da das OP-System eine schlechtere Single-Thread-Leistung als meine CPU, aber eine bessere Multi-Thread-Leistung aufweist, erwarte ich, dass diese Zahl korrekt ist.)
Der Multithread-Teil ist aufgrund des Ablaichens von Threads ziemlich ineffizient. Ich könnte es wahrscheinlich besser machen, indem ich meine benutzerdefinierte Jobbibliothek nutze, aber diese hat Fehler unter Unix-Systemen. Eine Erklärung und fast identischen Code ohne Threading finden Sie unter https://codegolf.stackexchange.com/a/26485/20965 .
bearbeiten
Ich gab jedem Thread ein eigenes RNG und reduzierte die Bitlänge auf 32, was die Laufzeit um einige ms verkürzte.
Beispielausgabe:
quelle
C ++
x150x450x530Anstelle eines Arrays habe ich Bits (und dunkle Magie) verwendet.
Danke @ace für die schnellere Zufallsfunktion.
So funktioniert es: Die ersten 15 Bits der Ganzzahl
s
stellen das Array darS[15]
; Die Nullen stehen für -1, die Einsen für +1. Das ArrayF
ist auf ähnliche Weise aufgebaut. Aber mit zwei Bits für jedes Symbol.Verursache
S
undF
habe eine andere Darstellung, mit der ich mich verschachtelnS
muss, um vergleichbar zu seinF
.F
)F
)Jetzt können wir einfach Carnot verwenden, um das innere Produkt zu berechnen. Beachten Sie, dass eine Variable nur den Wert 00 oder 11 annehmen kann
0. 00 = 11 (-1 * -1 = +1)
0. 01 = 10 (-1 * 0 = 0)
0. 10 = 01 (-1 * 0 = 0)
0. 11 = 00 (-1 * +1 = -1)
1. 00 = 00 (+1 * -1 = -1)
1. 10 = 10 (+1 * 0 = 0)
1. 01 = 01 (+1 * 0 = 0)
1. 11 = 11 (+1 * +1 = +1)
Sieht aus wie ein Nicht-Xor für mich. :)
Alles in allem ist es nur ein Spiel mit Verschiebung und Maske, nichts wirklich Komplexes.
Hier eine Beispielausgabe:
Das Programm wurde kompiliert mit:
auf Fedora 20 mit gcc 4.8.2 Die CPU ist ein i7 8core.
Wahrscheinlich kann ich einige ms erhalten, die Compilerparameter zwicken.
Während dies die OP-Lösungszeit auf meinem Computer ist:
Bearbeiten:
Füge einfach openmp hinzu und ändere die Reihenfolge von, denn ich habe eine x3-Verstärkung, was zu einer x450-Leistungsverbesserung gegenüber dem OP-Code führt. : D In diesem Fall
leadingZero
muss das Array atomar sein. Die zufälligen globalen ... sind zufällig, sie werden zufälliger sein.müssen zum
-fopenmp
Compiler-Flag hinzugefügt werdenEdit: 2 Als Suggester von user71404 habe ich die Funktionen sumOnes und sumArray geändert und jetzt ist es superschnell.
Mit OpenMP ist langsamer, weil die Atomics zu viel Overhead hinzufügen.
Ohne Atomics geht es noch schneller, aber ich bekomme falsches Ergebnis.
2137992 1147218 619297 321243 155815 70946 32919 15579
Um sumArray zu verstehen, muss berücksichtigt werden, dass 16 Bit ein Array von 8 Zahlen darstellen.
00 habe keine 1 und repräsentiere -1
01 und 10 habe eine 1 und repräsentiere 0
11 habe zwei 1 und repräsentiere 1
Damit die eingebaute Anzahl der auf 1 gesetzten Bits zählt [ http://en.wikipedia.org/wiki/ Hamming_weight] und zu jeder Gruppe entfernen wir 1. Cool.
sumOnes ist nur schwarze Magie.
Hier kompilieren die neuesten Flags und Code.
gcc -std = c ++ 11 -mfpmath = sse -O3 -flto -march = native -funroll-loops -Wall -lstdc ++
quelle
inline int32_t sumOnes(int32_t v) { /* 0xAAAA == 0b1010 1010 1010 1010 */ return !! (0xAAAA & (v ^ ~(v << 1))); } inline int32_t sumArray(int32_t v) { return __builtin_popcount(v) - 8; }
Dies wurde von @ user71404Julia: 0,7s, 120x schneller
Wie user20768 gezeigt hat, ist ein unkomplizierter Port des Codes für Julia ungefähr doppelt so schnell wie PyPy. Aber wir können noch viel besser machen.
Sie können dies mit ausführen
julia -p 8 -e 'require("golf.jl");main()'
(die 8 ist die Anzahl der Prozesse, mit denen Sie möglicherweise herumspielen möchten). In der letzten Julia-Vorabversion dauert dies 0,7s gegenüber 1m22s für PyPy.Wenn Sie genug Kerne auf Ihrem Computer haben und vielleicht ein paar AWS-Instanzen hochfahren, sollten Sie in der Lage sein, weitere zu rasieren :)
quelle
C, 1,210 s
Mit OPs Code läuft 1m45.729s auf meinem Rechner.
Zusammenstellung:
Besonderer Dank geht an @dyp für die Zusammenstellung von Flags und Optimierungsideen.
Beispielausgabe:
quelle
-march=native -fwhole-program -fstrict-aliasing -ftree-vectorize
Btw. Ich bin mit etwas C ++ 11 auf <4 s gekommen, einschließlich eines MT19937 plus einesuniform_int_distribution
.F
.n
ist gleich,8
können Sie wahrscheinlich AVX (oder 2 * SSE) verwenden, um das Punktprodukt mit einem richtigenS
Speicher zu berechnen .smmintrin.h
)Perl
Dies ist bei weitem nicht so schnell wie die C-Lösung, aber für eine hochinterpretierte Sprache, denke ich, ziemlich schnell. Es spart etwa 40% der Laufzeit der Python-Implementierung.
Der Algorithmus :: Combinatorics ist in Ubuntu (
sudo apt-get install libalgorithm-combinatorics-perl
) verfügbar . Die anderen verwendeten Module sind Perl-Kernmodule und sollten daher bereits im Rahmen der Ubuntu-Basisinstallation installiert werden.quelle
0..N-1
Reichweite im letztenmap
, oder? Hast du es vergessenuse warnings
? :-) Obwohl die Logik in OP verwirrend ist, gelangt das Schiebefenster nie zum letzten Element vonS
.warnings
dass die fehlenden Elemente als Null behandelt werden.N-1
verbessert dies. Tatsächlich verbessert es die Geschwindigkeit geringfügig - es ist jetzt ungefähr 40% schneller als die Python-Implementierung.any
finden Sie alternativ in List :: MoreUtils, einem der am häufigsten verwendeten CPAN-Module, obwohl es sich nicht um ein Kernmodul handelt.Julia: 4.66x langsamer!
Ich fange wirklich an, die Statistiken auf ihrer Website zu bezweifeln ...
Beachten Sie, dass der folgende Julia-Code effektiv eine direkte Transkription des Python-Codes des OP ohne Optimierungen ist. Ich benutze die
time()
Funktion, um Julias langsame Startzeit auszuschließen ...Julia: 5 m 32,912 s
OP-Code in PyPy: 1 m 11.506 s
Julia Ausgabe:
quelle
RPython 0.187s (258x schneller)
Originalquelle mit PyPy2.2.1: 1m 6.718s
Mit Threading wurde die Unterstützung für Standard-Python aufgegeben. Die Anzahl der Worker-Threads kann als Befehlszeilenparameter angegeben werden. Der Standardwert ist zwei.
RPython ist eine eingeschränkte Teilmenge von Python, die in C übersetzt und dann mit der RPython-Toolchain kompiliert werden kann . Ihr ausdrücklicher Zweck ist es, die Erstellung von Sprachinterpreten zu unterstützen, aber sie können auch dazu verwendet werden, einfache Programme wie das oben beschriebene zu kompilieren. Die meisten der "schickeren" Funktionen von Python, wie z. B.
itertools
oder sogarmap
nicht verfügbar.Erstellen Sie zum Kompilieren einen lokalen Klon des aktuellen Pypy-Repositorys und führen Sie Folgendes aus:
Die resultierende ausführbare Datei wird
convolution-c
im aktuellen Arbeitsverzeichnis benannt oder ähnlich.Ich habe die Eingabevariablen parametrisiert, daher sollte das Programm wie folgt ausgeführt werden:
den Beispielcode zu entsprechen.
Implementierungshinweise
S in itertools.product([-1,1], repeat = n+m-1)
wirdS in xrange(1<<n+m-1)
, interpretiertS
als Bitmap: [0
,1
] → [-1
,1
]Ebenso
F
ist auch ein Bit - Map, mit jeweils zwei Bits einen einzelnen Wert repräsentiert:[
00
,01
,10
,11
] → [-1
,0
,0
,1
]Eine Wahrheitstabelle wird zum Nachschlagen des Produkts verwendet, anstatt eine Multiplikation durchzuführen.
Da vorzeichenbehaftete 32-Bit-Ganzzahlen verwendet werden,
n
dürfen diese nicht größer als 15 undn+m
nicht größer als 31 sein. Mit demrpython.rlib.rbigint
Modul kann bei Bedarf eine beliebige Ganzzahlunterstützung erzielt werden .Die erste Iteration der Skalarproduktschleife wird abgewickelt und mit dem Nullitätstest von kombiniert
F
.Es wird ein Homebrew-PRNG verwendet, der als Quelle aufgeführt ist. Der Autor des Papiers weist einen Zeitraum von 2 32 -1 nach und behauptet, dass er alle Diehard-Tests mit Ausnahme eines bestand, obwohl ich dies nicht persönlich bestätigt habe.
Der zufällige Startwert ändert sich jede Millisekunde, was bei Verwendung eines Zeitstempels so gut wie möglich ist. Darüber hinaus weist jeder Arbeitsthread
xor
seine Prozess-ID mit diesem Wert auf, um sicherzustellen, dass jeder einen anderen Startwert hat.Beispiel-Timings
2 Arbeitsthreads:
4 Arbeitsthreads:
8 Arbeitsthreads:
Originalquelle von OP:
Timing für 100000 Iterationen:
quelle
Julia: 1 min 21.4s (2.2x schneller) (Änderung von Armans Code)
Ops Code in PyPy: 3 min 1,4 s
Beides erfolgt in der REPL, ohne Zeit zum Laden von Paketen.
Es gibt einige Probleme damit, dass Armans Code sehr langsam ist: Er verwendet unnötigerweise viele anonyme Funktionen und Funktionen höherer Ordnung. Um zu testen, ob der gesamte Vektor F Null ist, schreiben Sie einfach alle (F == 0) anstelle aller (x-> x == 0, F). Es ist kürzer und buchstäblich tausendmal schneller.
Es wird auch sum (map (*, x, y)) als Skalarprodukt verwendet, anstatt nur Skalar (x, y). Die erste Version ist 650-mal langsamer für einen Vektor von 10k-Doubles. Und die Skalarproduktfunktion ist als for-Schleife in pure Julia implementiert.
Auch das Array-Verständnis ist langsam. Es ist besser, [0,1,0, -1] [rand (1: 4, n)] anstelle von [[-1 0 0 1] [rand (1: 4)] für j = 1: n zu schreiben. .
Schließlich sind globale Variablen in Julia schlechte Juju. Julia ist nur dann schnell, wenn Sie Code so schreiben, dass die JIT- und Typinferenz funktioniert. Ein großer Teil davon ist die Typstabilität: Der Compiler muss sicherstellen können, dass sich der Typ einer Variablen beispielsweise innerhalb einer Schleife nicht ändert.
quelle
Nimrod
Beispielausgabe:
Nimrod kompiliert nach C, daher ist die Wahl des C-Compilers auch für das Backend von Bedeutung.
Kompilieren Sie mit clang mit:
Kompilieren Sie mit gcc mit:
Lassen
--passc:-flto
Sie es aus, wenn Sie einen älteren C-Compiler haben, der LTO nicht unterstützt. Lassen Sie die--cc=...
Option aus, wenn Sie mit der Standardauswahl für den C-Compiler zufrieden sind. Der Code erfordert Nimrod 0.9.4 oder 0.9.5 .Auf meinem Quadcore-iMac (2,66-GHz-Core i5) läuft der Code mit gcc 4.9 in ungefähr 0,15 Sekunden, mit clang in 0,16 Sekunden, verglichen mit 88 Sekunden für PyPy 2.2.1 (dh eine Beschleunigung um mehr als das Doppelte). Leider habe ich keinen Zugriff auf eine Maschine mit mehr als vier Kernen, auf der auch PyPy installiert ist oder auf der PyPy problemlos installiert werden kann, obwohl ich auf einem 64-Kern-AMD etwa 0,1 Sekunden (mit viel Messrauschen) erhalte Opteron 6376 1.4 GHz (nach / proc / cpuinfo) mit gcc 4.4.6.
Die Implementierung versucht, dem Original treu zu bleiben, anstatt den Code auf Kosten der Lesbarkeit zu optimieren, ohne auf offensichtliche Optimierungen zu verzichten. Interessanterweise ist die Schwanzrekursion in
initVecRand()
etwas schneller als eine Schleife mit einer break-Anweisung mit gcc und clang. Das manuelle Abrollen einer Iteration derconvolve
Testschleife innerhalb der Hauptschleife führte ebenfalls zu einer Beschleunigung, vermutlich aufgrund einer besseren Verzweigungsvorhersage.quelle
Java
Ich habe die obige C ++ - Lösung nach Java übersetzt:
Auf meinem Computer erhalte ich folgende Ausgabe für das Java-Programm:
Das OP-Programm läuft auf meinem Rechner ca. 53 Sekunden:
Das c ++ Programm führte nur ca. 0,15 Sekunden aus:
Das ist ungefähr 2,5x schneller als die entsprechende Java-Lösung (ich habe den VM-Start nicht ausgeschlossen). Diese Java-Lösung ist ca. 142x schneller als das mit PyPy ausgeführte Programm.
Da ich persönlich interessiert war, habe ich
iters
für Java und C ++ auf 100_000 gesetzt , aber der Faktor 2,5 hat nicht zugunsten von Java abgenommen, wenn etwas größer wurde.BEARBEITEN: Ich habe die Programme auf einem 64-Bit-Arch-Linux-PC ausgeführt.
EDIT2: Ich möchte hinzufügen, dass ich mit einer groben Übersetzung des Python-Codes begonnen habe:
Dieses Programm lief etwa 3,6 Sekunden:
Welches ist etwa 14-mal schneller als die PyPy-Lösung. (Die Auswahl der Standard-Zufallsfunktion gegenüber der FastRandom-Funktion führt zu einer Ausführungszeit von 5 Sekunden.)
quelle
Python 3.5 + numpy 1.10.1, 3.76 Sekunden
Die Tests wurden auf meinem Macbook Pro ausgeführt. Der OP-Code benötigte auf demselben Computer ~ 6 Minuten.
Der Grund, warum ich diese Frage beantworte, ist, dass ich nicht über 10 Reputationen verfüge und Teil I nicht beantworten kann :-p
In den letzten Tagen habe ich versucht, herauszufinden, wie man mit numpy massive Windungen effizient ausführt (ohne auf ein Paket eines Drittanbieters angewiesen zu sein, selbst scipy). Als ich während meiner Recherche auf diese Reihe von Herausforderungen stieß, beschloss ich, es auszuprobieren. Ich bin vielleicht zu spät zu diesem Spiel gekommen, aber hier ist mein Versuch, Python 3.5 und Numpy 1.10.1 zu verwenden.
Ich habe die S- und F-Arrays vorberechnet und das S-Array während der Durchführung der Faltung abgeflacht, was (basierend auf meinen Experimenten) die Geschwindigkeit von np.convolve ausnutzen könnte. Mit anderen Worten, da ich keine vektorisierte Faltungsroutine gefunden habe, habe ich den Code fälschlicherweise vektorisiert, indem ich das gesamte Array abgeflacht habe und gehofft, dass np.convolved die Vektorisierung unter der Haube für mich erledigen würde, was anscheinend funktioniert. Hinweis: Ich habe mode = 'same' verwendet und die führenden und nachfolgenden Elemente, die nutzlos waren, abgeschnitten.
Auf meinem Macbook Pro ergeben die Testergebnisse 3,76 Sekunden . Als ich den auf Python 3.5 geänderten OP-Code ausführte, hatte ich ungefähr 6 Minuten Zeit . Die Beschleunigung beträgt etwa das 100-fache.
Ein Nachteil ist, dass der Speicherbedarf ein Problem sein kann, wenn die Größen zu groß sind, da die S- und F-Arrays gespeichert werden sollen.
Ich habe die gleiche Methode für Teil I verwendet und auf meinem Laptop eine ~ 60-100-fache Geschwindigkeit erreicht.
Wenn jemand meinen Code testen und mir mitteilen könnte, wie er auf Ihrem Computer abläuft, würde ich mich sehr freuen, wenn ich alles auf meinem Macbook Pro tun würde!
quelle
J,
130x~ 50x Beschleunigung?Mal auf einem zufälligen Debian:
Ich denke, es gibt Raum für Verbesserungen.
quelle
pypy
,python
weshalb Ihr Skript 130x schneller zu sein scheint.C ++: x200 (4-Core i7, sollte auf 8-Core auf x400 skaliert werden)
Versuch einer einfacheren C ++ 11- Lösung (getestet mit VS 2012, gcc und clang) mit Parallelisierung.
Um dies zu kompilieren und unter Linux mit gcc 4.8.1 auszuführen:
Unter Linux müssen wir auch
std::launch::async
mehrere Threads erzwingen. Mir hat das in einer früheren Version gefehlt.In Visual Studio (2012+) sollte dies funktionieren, aber ein Release für das Timing erstellen ...
Auf meinem alten Dual Core i3 dauert das ~ 0,9 Sekunden. Auf meinem i7 Quad Core sind das 0,319s vs. 66 Sekunden.
Auf einem 8-Core i7 sollte dies im x400-Beschleunigungsbereich liegen. Das Wechseln zu Arrays im C-Stil würde das beschleunigen, aber ich war daran interessiert, bei C ++ - Containern zu bleiben. Für mich ist es interessant zu sehen, welche Beschleunigung Sie erzielen können, während Sie relativ nah an der Problemdomäne und auf einem relativ hohen Niveau bleiben. Ich denke, C ++ kann das wirklich gut. Bemerkenswert ist auch die relativ einfache Paralleisierung mit C ++ 11-Konstrukten.
Die Bit-Lösung von @ ilmale ist sehr cool und funktioniert für -1/1/0. Man könnte auch SSE auf diese werfen und vielleicht eine erhebliche Beschleunigung bekommen.
Über die Parallelisierung hinaus gibt es einen weiteren "Trick", der die Anzahl der Summierungen verringert. Beispielergebnisse: 6332947 2525357 1041957 438353 193024 87331 40902 19649
quelle
Fortran: 316x
Okay, Fortran: Ich habe eine
Beschleunigung vonbis zu106x155x160x316 x, wenn ich ein Xorshift-RNG und OpenMP auf einer 4-Kern-i7-CPU verwende. Ansonsten gibt es keine großen Tricks. Damit der Iterator S konstruiert, verwende ich nur die binäre Darstellung der 16-Bit-Ganzzahl i. Sie werden feststellen, dass der Code, abgesehen vom Inline-RNG und dem "Iterator" / Mapping von i nach S, genauso hoch ist wie der Python-Code.Bearbeiten: Das "Wenn" in Xorshift wurde entfernt, jetzt wird "r = abs (w / ...)" anstelle von "r = w / ..." verwendet. Geht von 106x bis 155x.
Edit2: Dies erzeugt 15x so viele Zufallszahlen wie die C ++ - Lösung. Wenn jemand eine Zero-Overhead-Lösung hat, um ein zufälliges int in ein Array von 0s und 1s in Fortran zu konvertieren, bin ich ganz Ohr. Dann könnten wir C ++ schlagen :)
Edit3: Die erste Bearbeitung führte zu einem Fehler, wie Lembik betonte. Dies ist jetzt behoben, mit einer winzigen Verbesserung der Geschwindigkeit. Ich werde versuchen, den Vorschlag von Eelvex zu nutzen, um die Geschwindigkeit zu erhöhen.
Edit4: Die Profilerstellung zeigte an, dass die Konvertierung in real und zurück in integer mit nint () langsam war. Ich habe dies durch eine Ganzzahldivision ersetzt, die sowohl skaliert als auch rundet und dabei von 160x auf 316x beschleunigt.
Kompilieren mit:
Beispielausgabe:
OP-Code:
quelle