Napisałem klasę wektorową 3D, używając wielu nieskomplikowanych kompilatorów SSE. Wszystko działało dobrze, dopóki nie zacząłem inicjować zajęć, które mają wektor 3D jako nowy. Doświadczyłem nieparzystych awarii w trybie zwolnienia, ale nie w trybie debugowania i na odwrót.SSE, wewnętrzne i wyrównanie
Więc czytałem kilka artykułów i doszedłem do wniosku, że muszę wyrównać klasy będące własnością instancji klasy wektorowej 3D do 16 bajtów. Więc po prostu dodaje _MM_ALIGN16
(__declspec(align(16)
) przed klasami tak:
_MM_ALIGN16 struct Sphere
{
// ....
Vector3 point;
float radius
};
To wydawało się rozwiązać ten problem na początku. Ale po zmianie jakiegoś kodu mój program ponownie zaczął się dziwnie załamywać. Przeszukałem sieć jeszcze bardziej i znalazłem artykuł o blog. Spróbowałem tego, co autor, Ernst Hot, zrobił, aby rozwiązać problem i działa również dla mnie. Dodałem nowe i usunąć operatorów do moich zajęć tak:
_MM_ALIGN16 struct Sphere
{
// ....
void *operator new (unsigned int size)
{ return _mm_malloc(size, 16); }
void operator delete (void *p)
{ _mm_free(p); }
Vector3 point;
float radius
};
Ernst wspomina, że ten aproach może być problematyczne, jak również, ale on po prostu linki do forum, które już nie istnieje, nie wyjaśniając, dlaczego to może być problematyczne.
Więc moje pytania to:
czym problem z określeniem operatorów?
Dlaczego dodawanie
_MM_ALIGN16
do wystarczającej definicji klasy?Jaki jest najlepszy sposób poradzenia sobie z problemami związanymi z dopasowaniem pochodzącymi z samoistną SSE?
Czy w pierwszym przypadku przydzielacie swoje konstrukcje do stosu lub sterty? Nie jestem pewien, czy malloc wraca domyślnie do pamięci wyrównanej, podczas gdy _mm_malloc na pewno by - co masz na myśli mówiąc "po jakimś czasie mój program znowu zaczął się zawieszać"? Masz na myśli, że po opuszczeniu go działa na trochę (i co to było)? – Thomas
Problemy zaczęły się, gdy zacząłem przydzielać struktury na stercie. W zdaniu "po chwili" mam na myśli to, że zaczął się on zawiesza po zmianie kodu. Sądzę, że wyrównanie było słuszne przez przypadek, a potem je zniszczyłem. Myślę, że malloc nie zwraca 16 bajtów wyrównanych, co jest problemem, jak sądzę. Moje pytanie brzmi tak naprawdę, jaki jest problem z podejściem operatora i jaki jest najlepszy sposób zarządzania kodem za pomocą wewnętrznej samoistności SSE. –
W rzeczywistości nie trzeba określać wyrównania 'Sphere' (używając tej rzeczy' _MM_ALIGN16'), ponieważ kompilator jest wystarczająco inteligentny, aby zobaczyć, że 'Sphere' ma element wyrównany do 16 i automatycznie dostosowuje' Sphere' ' s wymagania wyrównania (biorąc pod uwagę, że "Vector3" jest prawidłowo wyrównany). Właśnie dlatego nie musisz jawnie wyrównywać "Vector3", jeśli ma już element '__m128'. To tylko alokacja dynamiczna jest problemem i można to przezwyciężyć przez przeciążenie 'operator new/delete', jak napisano na blogu (i zwykle dodatkowe rzeczy, takie jak specjalizacja' std :: allocator'). –