Warum std :: reduzieren Notwendigkeit commutability

stimmen
5

https://en.cppreference.com/w/cpp/algorithm/reduce

Er sagt, dass das Verhalten einer Operation nicht definiert ist, wenn der Vorgang nicht kommutativ ist, aber warum? Wir teilen nur das Array in Blöcke und dann das Ergebnis verschmelzen, ist es nur notwendig, um die Assoziativität?

Veröffentlicht am 13/02/2020 um 21:51
quelle vom benutzer
In anderen Sprachen...                            


3 antworten

stimmen
1

Das Verhalten ist eigentlich nicht-deterministisch, wenn die Operation zwischen den Operanden nicht kommutativ ist. „Nicht-deterministisch “ ist nicht dasselbe wie „unbestimmt“. Punkt math Schwimmdock ist nicht kommutativ, zum Beispiel. Dies ist ein Grund , warum ein Anruf std::reducekann nicht sein , deterministisch , da die binäre Funktion in einer nicht spezifizierten Reihenfolge angewandt wird.

Siehe diese Bemerkung in der Norm:

Anmerkung: Der Unterschied zwischen reduceund accumulateist das zu reduzieren gilt binary_opin einer nicht spezifizierten Ordnung, die eine nichtdeterministische Folge für nicht assoziative oder nicht-kommutative binary_op wie Gleitkommaaddition ergibt. -Ende note]

Beantwortet am 13/02/2020 um 22:02
quelle vom benutzer

stimmen
1

Die Norm legt die verallgemeinerte Summe wie folgt: numeric.defns

Definieren GENERALIZED_NONCOMMUTATIVE_SUM (op, a1, ..., aN) wie folgt:

  • A1, wenn n 1 ist, andernfalls

  • op (GENERALIZED_NONCOMMUTATIVE_SUM (op, a1, ..., ak), OP (GENERALIZED_NONCOMMUTATIVE_SUM (op, aM, ..., aN)) für jedes k, wobei 1

Definieren GENERALIZED_SUM (op, a1, ..., aN) als GENERALIZED_NONCOMMUTATIVE_SUM (op, b1, ..., bn), wobei b1, ..., bn jede Permutation von a1 sein kann, ..., aN.

So wird die Reihenfolge der Summation sowie die Reihenfolge der Operanden ist nicht spezifiziert. Wenn also die binäre Operation nicht kommutativ oder nicht assoziativ ist, ist das Ergebnis nicht spezifiziert.

Das ist auch ausdrücklich erwähnt hier .

Warum in Bezug auf : Es gibt die Bibliothek mehr Freiheit - Anbieter, so kann sie oder er kann es nicht besser umzusetzen. Als ein Beispiel , wo die Umsetzung von commutativity profitieren kann. Betrachten wir die Summe a+b+c+d+e, wir zuerst berechnen a+bund c+dparallel. Nun a+bkehrt vor c+dtut (wie es geschehen kann, weil es parallel durchgeführt). Statt für den Rückgabewert des Wartens c+dnun direkt können wir berechnen , (a+b)+eund dann auf das Ergebnis dieses Ergebnis hinzufügen c+d. Also am Ende, berechnet wir ((a+b)+e)+(c+d), die eine Umlagerung a+b+c+d+e.

Beantwortet am 13/02/2020 um 22:07
quelle vom benutzer

stimmen
6

std::reducesowohl Assoziativität und Kommutativität erfordert. Assoziativität ist eindeutig für einen parallelen Algorithmus benötigt, da man die Berechnung auf separaten Blöcken durchführen möchten und kombinieren sie dann.

Was commutativity: Nach einem reddit Beitrag von MSVC STL Entwickler Billy O'Neal, ist dies erforderlich , um Vektorisierung zu SIMD - Befehle zu ermöglichen:

Commutativity ist auch notwendig, Vektorisierung zu ermöglichen, da der Code, den Sie für reduzieren wollen wie so etwas zu kommen:

vecRegister = load_contiguous(first);
while (a vector register sized chunk is left) {
    first += packSize;
    vecRegister = add_packed(load_contiguous(first), vecRegister);
}
// combine vecRegister's packed components

usw., die gegeben ints und SSE-Register und a * b * c * d * e * f * g * h etwas wie (a * e) * (b * f) * (c * g) * (d * h ergibt ).

Die meisten anderen Sprachen tun nicht explizit Dinge zu deren Reduktion möglich zu machen Vektorisierung. Und nichts sagt, wir können keine noncommutative_reduce oder so etwas in der Zukunft hinzufügen, wenn jemand mit einem überzeugenden Anwendungsfall kommt.

Beantwortet am 13/02/2020 um 22:13
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more