Gram z wbudowanym asemblerem D's i SSE, ale znalazłem coś, czego nie rozumiem. Kiedy próbuję dodać dwa wektory float4 natychmiast po deklaracji, obliczenia są poprawne. Jeśli umieściłem obliczenia w oddzielnej funkcji, otrzymam serię nan
s.Nieznajoma SSE z funkcjami
//function contents identical to code section in unittest
float4 add(float4 lhs, float4 rhs)
{
float4 res;
auto lhs_addr = &lhs;
auto rhs_addr = &rhs;
asm
{
mov RAX, lhs_addr;
mov RBX, rhs_addr;
movups XMM0, [RAX];
movups XMM1, [RBX];
addps XMM0, XMM1;
movups res, XMM0;
}
return res;
}
unittest
{
float4 lhs = {1, 2, 3, 4};
float4 rhs = {4, 3, 2, 1};
println(add(lhs, rhs)); //float4(nan, nan, nan, nan)
//identical code starts here
float4 res;
auto lhs_addr = &lhs;
auto rhs_addr = &rhs;
asm
{
mov RAX, lhs_addr;
mov RBX, rhs_addr;
movups XMM0, [RAX];
movups XMM1, [RBX];
addps XMM0, XMM1;
movups res, XMM0;
} //end identical code
println(res); //float4(5, 5, 5, 5)
}
Zespół funkcjonalnie identyczne (o ile można powiedzieć) do this link.
Edycja: Używam niestandardowej struktury float4 (na razie jest to tylko tablica), ponieważ chcę mieć funkcję dodawania, taką jak float4 add(float4 lhs, float rhs)
. W tej chwili, że powoduje błąd kompilatora tak:
Error: floating point constant expression expected instead of rhs
Uwaga: Używam DMD 2.071.0
Mam nadzieję, że nie planujesz używać takiego kodu do wydajności. Zmuszasz kompilator do przechowywania wektorów w pamięci, a następnie zapisujesz te adresy w pamięci. Później piszesz kod, który ładuje adresy z pamięci i ponownie ładuje wektory. (W Windows 'vectorcall' ABI oraz w ABI SysV używanym przez wszystkie inne systemy AMD64, wektorowe argumenty są przekazywane w wektorowych rejestrach). W D, IDK, jeśli 'lhs_addr' może być rejestrem, ale nadal jest to bezużyteczny ruch registracyjny. Idealnie istnieje składnia dla zapytania o wektory w określonych regach, jak GNU C inline asm. –
Próbuję napisać własny typ float4, ponieważ 'float4 rhs_vec = [rhs, rhs, rhs, rhs];' jest niedozwolone z błędem w pytaniu. W tej chwili zasadniczo skopiowałem kod z linku i wykonałem kilka drobnych zmian, aby (miejmy nadzieję) sprawiły, że działał w D. W tej chwili to po prostu musi zadziałać. Ale co byś zrobił zamiast sekcji? To tylko moja trzecia podróż do montażu, więc każda korekta byłaby doceniona. – Straivers
Nie wiem D, właśnie widziałem to pytanie z powodu tagów SSE i inline-asm. Czy D ma coś takiego jak wewnętrzna Intel®? '__m128 my_vec = _mm_add_ps (vec1, vec2);'? Jeśli tak, prawdopodobnie lepiej sobie z tym poradzisz. Jeśli wbudowana składnia ASm jest ograniczona do przekazywania danych przez pamięć, a nie do rejestrów, to [jest to przydatne tylko wtedy, gdy chcesz napisać całą pętlę wewnątrz, a nie jako opakowanie dla kilku instrukcji] (http://stackoverflow.com/ pytania/3323445/jaka jest różnica między asem/asmem/35959859 # 3595985). Jeśli obsługuje instrukcje asm w stylu GNU-C, użyj tego. –