In der Standarddokumentation für std::transform
habe ich festgestellt, dass das Funktorargument bis C ++ 11 keine Nebeneffekte haben musste, während ab C ++ 11 die Anforderung weniger restriktiv war - "op und binary_op soll Iteratoren oder Teilbereiche nicht ungültig machen oder Elemente in den Bereichen ändern ". Siehe
und Abschnitt 25.3.4 des Standards. Die Webseite auf cppreference.com erwähnt auch, dass "die Absicht dieser Anforderungen ist, parallele oder Out-of-Order-Implementierungen von std::transform
zu erlauben".
Ich verstehe nicht, ob dieser Codeschnipsel in C ++ 11 legal ist oder nicht:
%Vor% Klar, wenn std::transform
hinter den Kulissen parallelisiert wird, haben wir mehrere gleichzeitige Aufrufe von foo += 1
, was UB sein wird. Aber der Funktor selbst scheint die im Standard beschriebenen Anforderungen nicht zu verletzen.
Diese Frage kann nach anderen Standardalgorithmen gestellt werden (außer ich denke std::for_each
, die explizit angibt, dass die Iteration in der richtigen Reihenfolge ausgeführt werden soll).
Habe ich etwas falsch verstanden?
Soweit ich die C ++ 11-Spezifikation verstehe, müssen alle Standardbibliotheksfunktionen alle ihre Operationen nacheinander ausführen, wenn ihre Auswirkungen für den Benutzer sichtbar sind. Insbesondere müssen alle "mutierenden Sequenzoperationen" sequentiell durchgeführt werden.
Der relevante Teil der Norm ist §17.6.5.9 / 8:
Sofern nicht anders angegeben, führen die C ++ - Standardbibliotheksfunktionen alle Operationen nur innerhalb des aktuellen Threads durch, wenn diese Operationen Auswirkungen haben, die für Benutzer sichtbar sind (1.10).
Die Art und Weise, wie die Algorithmen derzeit definiert sind, müssen sequentiell ausgeführt werden, es sei denn, die Implementierung kann beweisen, dass ihre gleichzeitige Ausführung die Semantik nicht ändert. Ich könnte mir eine zukünftige Hinzufügung für Algorithmen vorstellen, die explizit gleichzeitig ausgeführt werden dürfen, aber sie wären andere Algorithmen.
So erlaubt C ++ 11 nun, dass std::transform
parallelisiert wird, aber das ist keine Garantie, dass Ihr eigener Code parallelisierungssicher gemacht wird. Nun ja, ich nehme an, Sie müssen Ihre Datenvariablen schützen. Ich kann mir viele MT-Bugs vorstellen, die sich daraus ergeben, wenn Implementierungen tatsächlich tatsächlich std::transform
paralellisieren.