Hvorfor std :: redusere behovet commutability

stemmer
5

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

Den sier at oppførselen til en operasjon ikke er definert hvis operasjonen er ikke kommutativ, men hvorfor? Vi bare dele tabellen i blokker og deretter flette resultatet, er det bare nødvendig å assosiativitet?

Publisert på 13/02/2020 klokken 21:51
kilden bruker
På andre språk...                            


3 svar

stemmer
1

Virkemåten er faktisk ikke-deterministisk dersom operasjon mellom operandene er ikke kommutativ. "ikke-determinis" er ikke det samme som "udefinert". Flyttall matematikk er ikke kommutativ, for eksempel. Dette er en grunn til at en oppfordring til std::reduceikke kan være deterministisk, fordi det binære funksjonen er brukt i en uspesifisert rekkefølge.

Referere til dette notatet i standarden:

Merk: Forskjellen mellom reduceog accumulateer som reduserer gjelder binary_opi en uspesifisert ordre, noe som gir et resultat nondeterministic for ikke-assosierende eller ikke-kommutativ binary_op slik som flytpunkttilsetningen. -End note]

Svarte 13/02/2020 kl. 22:02
kilden bruker

stemmer
1

Standarden definerer den generaliserte sum som følger: numeric.defns

Definer GENERALIZED_NONCOMMUTATIVE_SUM (op, a1, ..., an) som følger:

  • a1 når n er 1, ellers

  • op (GENERALIZED_NONCOMMUTATIVE_SUM (op, a1, ..., ak), op (GENERALIZED_NONCOMMUTATIVE_SUM (op, aM, ..., an)) for en hvilken som helst K hvor ett

Definer GENERALIZED_SUM (op, a1, ..., An) som GENERALIZED_NONCOMMUTATIVE_SUM (op, b1, ... BN), hvor B1, ..., bN kan være enhver permutasjon av a1, ..., An.

Så, er rekkefølgen på summering samt rekkefølgen av operander uspesifisert. Så hvis det binære operasjonen er ikke kommutativ eller ikke assosiativ, er resultatet uspesifisert.

Det er også uttrykkelig angitt her .

Angående hvorfor: Det gir biblioteket leverandører mer frihet, slik at de kan eller ikke kan gjennomføre det bedre. Som et eksempel hvor gjennomføringen kan dra nytte av commutativity. Tenk summen a+b+c+d+e, må vi først beregne a+bog c+dparallelt. Nå a+breturnerer før c+dgjør (som det kan skje, fordi det er gjort i parallell). I stedet for å vente på returverdien av c+dvi nå kan direkte beregne (a+b)+eog deretter legge dette resultatet til resultatet av c+d. Så til slutt, vi beregnet ((a+b)+e)+(c+d), som er en omorganisering av a+b+c+d+e.

Svarte 13/02/2020 kl. 22:07
kilden bruker

stemmer
6

std::reducekrever både assosiativitet og commutativity. Assosiativitet er klart behov for en parallell algoritme, siden du ønsker å utføre beregningen på separate biter og deretter kombinere dem.

Som for commutativity: Ifølge en reddit innlegg av MSVC STL utvikler Billy O'Neal, er dette nødvendig for å tillate vektorisering til SIMD instruksjoner:

Commutativity er også nødvendig for at vektorisering, siden koden du ønsker for å redusere å komme ut som noe sånt som:

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

etc., som angitt ints og SSE registre og a * b * c * D * E * F * g * h gir noe som (a * E) * (b * f) * (c * g) * (d * h ).

De fleste andre språk gjør ikke eksplisitte ting å gjøre vectorizing deres reduksjon mulig. Og ingenting sier at vi ikke kan legge til en noncommutative_reduce eller noe sånt i fremtiden hvis noen kommer opp med en overbevisende use case.

Svarte 13/02/2020 kl. 22:13
kilden bruker

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