Berechnung von "(id - (id % width)) / width" beschleunigen?

Gast #2711210
Lesenswert?

Jo, habe woanders noch eine Größe zweimal berechnet. Vorberechnen hat 
nochmal ca. 10% Geschwindigkeit gebracht.

Es geht darum, Indices für die Ausgabe der berechneten Werte zu 
bestimmen (FFT). Diese Prozedur verschlingt bei Radix-2 FFT ca. die 
Hälfte der Zeit, wenn man das out-of-place macht (was ich machen muss, 
da ich OpenCL nutze und in-place wegen der Synchronisierung nicht für 
große FFTs geht).
1
    int id = get_global_id(0);  // thread index
2

3
    // width of each FFT block in the current stage
4
    int width = (int)exp2((float)(stage - 1));
5
    
6
    // the offset for a certain FFT block in the output index
7
    int offset = id / width;
8
    
9
    // input and output indices
10
    int inA = id;
11
    int inB = id + NThread;
12
    int outA = id % width + offset * 2 * width;
13
    int outB = outA + width;

inA, inB sind die Indices der beiden Eingänge und outA, outB der 
Ausgänge. Ich habe schon einiges optimiert und dadurch ca. doppelte 
Geschwindigkeit erreicht. Aber vielleicht gibt es noch weitere 
Möglichkeiten, die ich nicht sehe?

(Für Skizze siehe http://cnx.org/content/m12012/latest/#fig:inplace )
#2711949
Lesenswert?

Maik M. schrieb:
> was mir gerade aufgefallen ist, so könnte es auch gehen:
> int outA = id<<1 - id%width;

wo kommt das minus her

*2 durch shifts optimieren macht der Compiler.
Zumal es auch nicht immer sinn macht.
"x*8" rechnet zB ein Avr schneller als "x<<3"

Maik M. schrieb:
> int offset = id / width;
> int outA = id % width + offset  2  width;

-->

outA = id % width + (id / width)* 2 * width;
     = id % width + id * 2 ;
#2711986
Lesenswert?

Vlad Tepesch schrieb:
> outA = id % width + (id / width)* 2 * width;
>      = id % width + id * 2 ;

bei ganzzahliger Division verschwinden die Nachkommastellen
1
outA = 3 % 2 + (3 / 2) * 2 * 2 = 1 + 4;
2
outA = 3 % 2 + 3 * 2 = 1 + 6;

zu deiner Frage mit dem Minus:
1
Ausgangsgleichung:
2
int outA = (id % width) + (id / width) * 2 * width;
3

4
(id/width)*width = id - (id % width)
5

6
daraus ergibt sich:
7
int outA = (id % width) + (id - (id % width)) * 2;
8
int outA = (id % width) + 2*id - 2*(id % width);
9
int outA = 2*id - (id % width);
10
int outA = id<<1 - (id % width);
#2712285
Lesenswert?

Maxim schrieb:
> Weitere 10%, danke! ;)

aber achtung
Das verändert das Ergebnis.

Maik M. schrieb:
> bei ganzzahliger Division verschwinden die Nachkommastellen


Es treten bei meiner Rechnung weniger Rundungsfehler auf - kann ja aber 
sein, dass das gewollt war

Maxim schrieb:
> Wobei 2*id und id<<1 gleich schnell sind.

das schrieb ich ja: solche optimierungen sollte man dem Compiler 
überlassen.
wenn man Multiplikation meint, schreibt man das was mein meint, nämlich 
*
und wenn man die bitschiebeoperation will, schreibt man <<
Der Compilier weiß schon ganz gut, wie das optimal umgesetzt wird.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren