2015-04-30 24 views
5

Mam strukturę, która wygląda tak:najszybsze Struct-of-tablic do Array-of-kodowanym Conversion

struct SoA 
{ 
    int arr1[COUNT]; 
    int arr2[COUNT]; 
}; 

I chcę, żeby wyglądać tak:

struct AoS 
{ 
    int arr1_data; 
    int arr2_data; 
}; 

std::vector<AoS> points; 

jako tak szybko jak to możliwe. Zamówienie musi zostać zachowane.

Konstruuje każdy obiekt AoS indywidualnie i przesyła go z powrotem w najszybszy sposób, aby to zrobić, czy jest szybsza opcja?

SoA before; 
std::vector<AoS> after; 

for (int i = 0; i < COUNT; i++) 
    points.push_back(AoS(after.arr1[i], after.arr2[i])); 

Istnieją pytania związane z SoA/AoS dotyczące StackOverflow, ale nie znalazłem jednego związanego z najszybszą możliwą konwersją. Ze względu na różnice w strukturze pakietów nie widzę sposobu, aby uniknąć kopiowania danych z jednego formatu do drugiego, ale mam nadzieję, że ktoś może mi powiedzieć, że istnieje sposób na proste odwoływanie się do danych i unikanie kopii.

Niezwykle zachęcające rozwiązania ścienne.

+0

Wątpię, czy możesz "po prostu inaczej odnieść się do danych", ponieważ ma on inne ustawienie w pamięci. – immibis

+0

I będziesz musiał włożyć/wepchnąć je mimo to, w przeciwnym razie twój "wektor" nie będzie w prawidłowym stanie. –

+1

Należy zauważyć, że odwoływanie się do danych w inny sposób może nie być rzeczywiście szybsze niż wykonanie kopii ... Pamięć podręczna RAM jest najbardziej efektywna podczas odczytu lub zapisu pamięci liniowo, a wykonanie wielu dereferencji może spowodować jej przerwanie, powodując wiele braków w pamięci podręcznej. i dlatego wolniejsze wykonanie. (a może nie, ale najważniejszą rzeczą jest zmierzenie go w obie strony i przygotuj się na zaskoczenie, gdy twoje intuicje nie pasują do rzeczywistości). –

Odpowiedz

5

Układ binarny z SoA i AoS[]/std::vector<AoS> jest inny, więc naprawdę nie ma sposobu na przekształcenie się bez obsługi kopiowania.

Kod, który masz, jest bardzo zbliżony do optymalnego - jedną poprawkę może być wstępna alokacja wektora z oczekiwaną liczbą elementów. Alternatywnie spróbuj surowej tablicy zarówno przy konstruowaniu całego elementu, jak i inicjalizacji dla właściwości. Zmiany muszą być mierzone ostrożnie (zdecydowanie mierz w oparciu o w pełni zoptymalizowaną kompilację z oczekiwanymi rozmiarami macierzy) i ważone względem czytelności/poprawności kodu.

Jeśli nie potrzebujesz dokładnego układu binarnego (wydaje się, że tak jest w przypadku, gdy korzystasz z wektora), możesz być w stanie osiągnąć podobnie wyglądającą składnię, tworząc pary niestandardowych klas, które inaczej prezentowałyby istniejące dane. Pozwoli to całkowicie uniknąć kopiowania.

będzie trzeba „array” typu (przedstawić indeksowania/iterację po wystąpieniu SoA) i „element” typu (inicjalizowane referece na przykład SOA i wskaźnik, odsłaniając dostępowych, w oddzielnych obszarach w tym indeksie)

Szorstki szkic kodu (dodaj iteratory, ...):

class AoS_Element 
{ 
    SoA& soa; 
    int index; 
public: 
    AoS_Element(SoA& soa, int index) ... 
    int arr1_data() { return soa.arr1[index];} 
    int arr2_data() { return soa.arr2[index];} 
} 

class AoS 
{ 
    SoA& soa; 
public: 
    AoS(SoA& _soa):soa(_soa){} 
    AoS_Element operator[](int index) { return AoS_Element(soa, index);} 
} 
+0

Czy możesz rozwinąć podany typ tablicy? Masz rację, dokładna reprezentacja binarna nie jest tutaj celem, tylko skutecznym dostępem do elementów. Nie myślałem o używaniu niestandardowego iteratora –

+0

@ConnorLawson Dodałem bardzo szorstką próbkę (prawdopodobnie nawet nie skompiluję ... mam nadzieję, że pokażę, co mam na myśli lepiej niż słowa). –

+0

'std :: vector' content ma identyczny układ binarny do zwykłej starej tablicy. –