» »

GNU C++ SSE PROBLEM

GNU C++ SSE PROBLEM

bbspin ::

Vertex Matrix::operator * (const Vertex &v) const
{
Vertex r;

__asm__ volatile
(
"movss (%[v]), %%xmm0 \n\t"
"shufps $0, %%xmm0, %%xmm0 \n\t"
"movss 4(%[v]), %%xmm1 \n\t"
"mulps (%[m]), %%xmm0 \n\t"
"shufps $1, %%xmm1, %%xmm1 \n\t"
"movss 8(%[v]), %%xmm2 \n\t"
"mulps 16(%[m]), %%xmm1 \n\t"
"shufps $0, %%xmm2, %%xmm2 \n\t"
"movss 12(%[v]), %%xmm3 \n\t"
"mulps 32(%[m]), %%xmm2 \n\t"
"shufps $0, %%xmm3, %%xmm3 \n\t"
"addps %%xmm1, %%xmm0 \n\t"
"mulps 48(%[m]), %%xmm3 \n\t"
"addps %%xmm3, %%xmm2 \n\t"
"addps %%xmm2, %%xmm0 \n\t"
"movups %%xmm0, (%[r]) \n\t"
"movw $1, 12(%[r]) \n\t" : [r] "=mr" (r) : [v] "mr" (&v), [m] "mr" (this) : "xmm0", "xmm1", "xmm2", "xmm3"
);
return r;
}

javi mi napako:
/tmp/cc8bu4Jt.s: Assembler messages:
/tmp/cc8bu4Jt.s:151: Error: register value used as expression
/tmp/cc8bu4Jt.s:152: Error: junk `((%edi))' after expression

to sta sigurno zadnji dve vrstici assemblerske kode...
ce ju zakomentiram mi dela, samo potem vseeno kreshne...

prej sm mel mal drugac narjen, pa mi je pravilno delal, zracunal vse uredu, sam je po nekaj zracunanih mnozenj prislo do seg. fault-a...
mogoce kdo vid se kksno napako?

bojan

BigWhale ::

Nevem sicer kako je z ASM ampak men se na konc zdi mau prevec dvopicij in narekovajev?

fiction ::

Vse skupaj bi lahko napisal kot:

...
"movups %%xmm0, (%[r]) \n\t"
"movw $1, 12(%[r]) \n\t"
: [r] "=mr" (r)
: [v] "mr" (&v), [m] "mr" (this)
: "xmm0", "xmm1", "xmm2", "xmm3"

Te zadnje tri vrstice niso assembler, ampak output, input
in clobber list (po domace kaj vracas, kaj je zate input in
kaj vse si spremenil).
Torej tisti xmm0 - xmm3 so tam ker si dejansko te registre spremenil
in moras to gcc-ju povedati (da jih ne uporabi ze on v kaksni optimizaciji).
: [r] "=mr" (r) - tole pomeni r je alias za izhodno spremenljivko
r, ki je bodisi v registru procesorja ali nekje v pomnilniku.

: [v] "mr" (&v), [m] "mr" (this)
vhodi so pa v kakor poimenujes &v in this, ki mu pravis m.
(As of GCC version 3.1, one may write [name] instead of the operand number for a matching constraint.)

Ko imas v kodi recimo
"mulps 32(%[m]), %%xmm2 \n\t"

to potem pomeni "mulps 32(this), %xmm2".

%edi je pac nek register, ki ga izbere gcc zaradi "r".

Bolj bi pomgalo ce bi tocno vedel v kateri vrstici dobis napako, se mi pa zdi cudno, da je r
kvazi izhod, ko pa nikjer ne pises v r, ampak samo na naslov kamor kaze r in neke odmike od tega.

bbspin ::

teli vrstici sta problem:

"addps %%xmm2, %%xmm0 \n\t"
"movups %%xmm0, (%[r]) \n\t"

prej sm mel constrainte tkole, pa je delal:
: : [r] "mr" (r), [v] "mr" (&v), [m] "mr" (this) : "xmm0", "xmm1", "xmm2", "xmm3"

sam je pol po ene 200 uspesnih izvedb te kode prslo do segmentation fault-a... pa sm mislu da bi blo bols definirat
Vertex r kot izhod...

Sm bil navajn programirat inline v intel sintaksi... pa me tale AT&T sistem se mal jebe :D
bom probu se mal z debugerjem pogledat kje se zalom...

ce pa ves kako definirat Vertex r kot izhod pa povej... mislm da mi sam kot "m" ne dela, pa sm fliknu pol se register zravn, se prav "mr"...

bbspin ::

__asm__ volatile
(
"movups (%[m]), %%xmm4 \n\t"
"movups 16(%[m]), %%xmm5 \n\t"
"movups 32(%[m]), %%xmm6 \n\t"
"movups 48(%[m]), %%xmm7 \n\t"
"movss (%[v]), %%xmm0 \n\t"
"shufps $0, %%xmm0, %%xmm0 \n\t"
"movss 4(%[v]), %%xmm1 \n\t"
"mulps %%xmm4, %%xmm0 \n\t"
"shufps $1, %%xmm1, %%xmm1 \n\t"
"movss 8(%[v]), %%xmm2 \n\t"
"mulps %%xmm5, %%xmm1 \n\t"
"shufps $0, %%xmm2, %%xmm2 \n\t"
"movss 12(%[v]), %%xmm3 \n\t"
"mulps %%xmm6, %%xmm2 \n\t"
"shufps $0, %%xmm3, %%xmm3 \n\t"
"addps %%xmm1, %%xmm0 \n\t"
"mulps %%xmm7, %%xmm3 \n\t"
"addps %%xmm3, %%xmm2 \n\t"
"addps %%xmm2, %%xmm0 \n\t"
"movups %%xmm0, (%[r]) \n\t"
"movw $1, 12(%[r]) \n\t"
:
: [r] "mr" (&r), [v] "mr" (&v), [m] "mr" (this)
: "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"
);

no za 1x, sm kr nalozu najprej vse vrstice matrik v xmm registre pa pol rajs mnozil z njimi..
pa zdej dela ok, bom se pol optimizeru za hitrost :)

bojan

bbspin ::

mislm da je bil problem v tem da mi je crknl po tolk in tolk uspesnih iteracijah to da verjetno mulps rabi met aligned memory ce direkt mnozis...

=> mulps 48(%[m]), %%xmm3 \n\t"

bbspin ::

sm pa stestiru funkcijo pa je blazno pocasna:) ma kdo kksn predlog za pohitritev, razno da dam movups v movaps...

bojan

bbspin ::

Vertex Matrix::operator * (const Vertex &v) const
{

Vertex r __attribute__ ((aligned(16)));

#ifndef SSE
r.x = v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0] + m[3][0];
r.y = v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1] + m[3][1];
r.z = v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2] + m[3][2];
r.t = 1.0f;
#else
__asm__ volatile
(
"movss (%[v]), %%xmm0 \n\t"
"shufps $0, %%xmm0, %%xmm0 \n\t"
"movss 4(%[v]), %%xmm1 \n\t"
"mulps 0(%[m]), %%xmm0 \n\t"
"shufps $0, %%xmm1, %%xmm1 \n\t"
"movss 8(%[v]), %%xmm2 \n\t"
"mulps 16(%[m]), %%xmm1 \n\t"
"shufps $0, %%xmm2, %%xmm2 \n\t"
"movss 12(%[v]), %%xmm3 \n\t"
"mulps 32(%[m]), %%xmm2 \n\t"
"shufps $0, %%xmm3, %%xmm3 \n\t"
"addps %%xmm1, %%xmm0 \n\t"
"mulps 48(%[m]), %%xmm3 \n\t"
"addps %%xmm3, %%xmm2 \n\t"
"addps %%xmm2, %%xmm0 \n\t"
"movaps %%xmm0, (%[r]) \n\t"
"movl $0x3f800000, 12(%[r]) \n\t"
:
: [r] "mr" (&r), [v] "mr" (&v), [m] "mr" (&mr)
: "xmm0", "xmm1", "xmm2", "xmm3"
);
#endif

return r;
}

no tole je koncna funkcija :) dela se zmer relativno pocasi... podatki pa morjo bit aligned16 da dela...
se kdo spozna na optimizacije v asm?

bojan

Senitel ::

Bemti... Pol ure gledam kodo in mi ni jasno kako hudiča sploh kar koli dela in potem preberem na netu da ima GCC drugačen vrstni red operandov kot Intel ASM.
Drgač pa:
-četrtega množenja ne rabiš, samo add
-namesto da "v" nalagaš vsakič posebej po en skalar spravi cel "v" v recimo xmm0 in potem prestavlji in shuffli v xmm1 recimo
To je pa se mi zdi vse kar se da še naredit.

bbspin ::

ja tale AT&T sucks, cista zmeda :/

tisto prvo sm ze ugotovu, da je bols naloudat z movups cel vektor na 1x... se sploh za SSE2 kjer lahko pol uporabs pshufd...
cetrtega mulp-a pa res ne rabs ce predpostavljas da je cetrti element vektorja zmeraj 1.

kako pa si mislu prestavljanje in shuflanje...

jest mam zdej tkole, dela samo malenkost hitreje:

__asm__ volatile
(
"movups (%[v]), %%xmm0 \n\t"
"movaps %%xmm0,%%xmm3 \n\t"
"movaps %%xmm0,%%xmm2 \n\t"
"movaps %%xmm0,%%xmm1 \n\t"
"shufps $0x00, %%xmm0, %%xmm0 \n\t"
"shufps $0xaa, %%xmm1, %%xmm1 \n\t"
"shufps $0x55, %%xmm2, %%xmm2 \n\t"
"shufps $0xff, %%xmm3, %%xmm3 \n\t"
"mulps 0(%[m]), %%xmm0 \n\t"
"mulps 16(%[m]), %%xmm1 \n\t"
"mulps 32(%[m]), %%xmm2 \n\t"
"mulps 48(%[m]), %%xmm3 \n\t"
"addps %%xmm1, %%xmm0 \n\t"
"addps %%xmm3, %%xmm2 \n\t"
"addps %%xmm2, %%xmm0 \n\t"
"movaps %%xmm0, (%[r]) \n\t"
"movl $0x3f800000, 12(%[r]) \n\t"
:
: [r] "mr" (&r), [v] "mr" (&v), [m] "mr" (&mr)
: "xmm0", "xmm1", "xmm2", "xmm3"
);

bbspin ::

se brez odvecnega mnozenja (ob prepostavki da je 4 element vektorja 1):

__asm__ volatile
(
"movups (%[v]), %%xmm0 \n\t"
"movaps %%xmm0,%%xmm2 \n\t"
"movaps %%xmm0,%%xmm1 \n\t"
"shufps $0x00, %%xmm0, %%xmm0 \n\t"
"shufps $0xaa, %%xmm1, %%xmm1 \n\t"
"shufps $0x55, %%xmm2, %%xmm2 \n\t"
"mulps 0(%[m]), %%xmm0 \n\t"
"mulps 16(%[m]), %%xmm1 \n\t"
"mulps 32(%[m]), %%xmm2 \n\t"
"movaps 48(%[m]), %%xmm3 \n\t"
"addps %%xmm1, %%xmm0 \n\t"
"addps %%xmm3, %%xmm2 \n\t"
"addps %%xmm2, %%xmm0 \n\t"
"movaps %%xmm0, (%[r]) \n\t"
"movl $0x3f800000, 12(%[r]) \n\t"
:
: [r] "mr" (&r), [v] "mr" (&v), [m] "mr" (&mr)
: "xmm0", "xmm1", "xmm2", "xmm3"
);

bbspin ::

se ena mjhna sprememba (k ne vem ce prinese kej k hitrosti :))

__asm__ volatile
(
"movups (%[v]), %%xmm0 \n\t"
"movaps %%xmm0,%%xmm1 \n\t"
"movaps %%xmm0,%%xmm2 \n\t"
"shufps $0x00, %%xmm0, %%xmm0 \n\t"
"shufps $0xaa, %%xmm1, %%xmm1 \n\t"
"shufps $0x55, %%xmm2, %%xmm2 \n\t"
"mulps 0(%[m]), %%xmm0 \n\t"
"mulps 16(%[m]), %%xmm1 \n\t"
"mulps 32(%[m]), %%xmm2 \n\t"
"addps %%xmm1, %%xmm0 \n\t"
"addps 48(%[m]), %%xmm2 \n\t"
"addps %%xmm2, %%xmm0 \n\t"
"movaps %%xmm0, (%[r]) \n\t"
"movl $0x3f800000, 12(%[r]) \n\t"
:
: [r] "mr" (&r), [v] "mr" (&v), [m] "mr" (&mr)
: "xmm0", "xmm1", "xmm2"
);

Senitel ::

To je to, hitrejše pa ne bo šlo, razen če je še kakšen catch z input dekleracijami (in pa pshufd kot si že ugotovil).

bbspin ::

jest tud mislm da sm ze bliz konca kar se tice SSE1... tole se mal pohitri, ce prefetcham zadnjo vrstico matrike...
mal se bom poigral se z vrstnim redom instrukcij....

__asm__ volatile
(
"movups (%[v]), %%xmm0 \n\t"
"movaps %%xmm0,%%xmm1 \n\t"
"movaps %%xmm0,%%xmm2 \n\t"
"shufps $0x00, %%xmm0, %%xmm0 \n\t"
"shufps $0xaa, %%xmm1, %%xmm1 \n\t"
"shufps $0x55, %%xmm2, %%xmm2 \n\t"
"prefetchT0 48(%[m]) \n\t"
"mulps 0(%[m]), %%xmm0 \n\t"
"mulps 16(%[m]), %%xmm1 \n\t"
"mulps 32(%[m]), %%xmm2 \n\t"
"addps %%xmm1, %%xmm0 \n\t"
"addps 48(%[m]), %%xmm2 \n\t"
"addps %%xmm2, %%xmm0 \n\t"
"movaps %%xmm0, (%[r]) \n\t"
"movl $0x3f800000, 12(%[r]) \n\t"
:
: [r] "mr" (&r), [v] "mr" (&v), [m] "mr" (&mr)
: "xmm0", "xmm1", "xmm2"
);

tnx :)

lp, bojan

Senitel ::

Je pa tko, če rabiš cel kup vektorjev transformirat (kjer se take zadeve itak največ poznajo) z eno matriko, se da to tudi lepo optimizirat.

bbspin ::

dej mal vec napis o tem:) se strinjam da se to najvec pozna...

jest sem imel namen samo pospesiti racunanje matrika * vertex, lahko se kako drugace?

lp, bojan

Senitel ::

Če imaš eno matriko in N vertexov (kar je običajno; no odvisno kaj točno počneš) lahko izkoristiš to dejstvo in ne nalagaš matrike vsakič posebej.
Link kjer je par primerov točno tega, kar ti počneš. ;)

Zgodovina sprememb…

  • spremenil: Senitel ()

bbspin ::

zakon, nice page... :) bom mal nastuderu :)

tnx,

bojan


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Prehod iz 32 na 64b - pointer registri?

Oddelek: Programiranje
51074 (851) Brane2
»

[C++ & asm] najhitrejša inicializacija 2D matrike

Oddelek: Programiranje
311769 (1409) Fury
»

Trčenje galaksij

Oddelek: Novice / Znanost in tehnologija
262902 (2902) Thomas
»

Kateri multimedijski program uporabljate in zakaj?

Oddelek: Zvok in slika
51101 (899) ABX

Več podobnih tem