Autor Wątek: Organizacja danych  (Przeczytany 3218 razy)

Offline kibiC++

  • Użytkownik

# Czerwiec 07, 2016, 22:44:02
Witam.
Na wstępie chciałbym nadmienić, że zdaje sobie sprawę, iż premature optimization to zło wcielone i ogień piekielny, ale ciekawość jest jednak silniejsza i chciałbym się dowiedzieć paru rzeczy :)

1.) Sporo można poczytać o efektywnym rozłożeniu danych ( hot/cold, cache-friendly, etc. ). Jak to się ma do architektury Unity skoro klasy w C# to typy referencyjne i jakiekolwiek grupowanie ich(jeśli takowe występuje) w tablice/listy to jedynie grupowanie referencji a same obiekty latają sobie gdzieś swobodnie po zakamarkach heapu?

2.) Czy spotkaliście się, a może sami używacie jakiegoś niekonwencjonalnego sposobu na grupowanie danych( stricte danych, nie referencji)?  (punkt można ominąć, jeśli moje rozumowanie pkt.1 jest błędne :))

3.) W wielu miejscach można wyczytać, żeby struktury raczej omijać z daleka, a jeśli już jest taka potrzeba to:
  a.) powinny być nie większe niż 16b
  b.) powinny być niemutowalne

4.) Czy zalecany maksymalny rozmiar struktur z pkt. 3a jest związany wyłącznie z tym, że structy przekazywane są przez wartość? Jeśli tak, to w czym problem przekazywać strukture przez ref?

PS. Nie wiedziałem czy temat dać tutaj czy dziale C#, tak że z góry przepraszam za ewentualny bałagan :)

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Rolek

  • Użytkownik

# Czerwiec 07, 2016, 23:04:44
3.) W wielu miejscach można wyczytać, żeby struktury raczej omijać z daleka, a jeśli już jest taka potrzeba to:
  a.) powinny być nie większe niż 16b
  b.) powinny być niemutowalne
Mógłbyś podać linka gdzie coś takiego wyczytałeś?

Offline lethern

  • Użytkownik

# Czerwiec 08, 2016, 02:47:10
Mógłbyś podać linka gdzie coś takiego wyczytałeś?
pewnie chodzi o boxing/unboxing struktur do obiektów

Offline strateg

  • Użytkownik

# Czerwiec 08, 2016, 11:26:29
Patrząc na różnice pomiędzy strukturami i klasami można zauważyć wiele ciekawych rzeczy. Przede wszystkim w przeciwieństwie do C++ różnice te są bardzo poważne. Przypisanie struktury do zmiennej powoduje utworzenie kopii. Łatwo więc zauważyć, że wszelkie operacje na kolekcjach mogą być bardzo kosztowne jeśli nie są robione rozsądnie. Dlatego też struktury są mocno odradzane, np. przy operacjach LINQ, gdzie przykładowo za każdym razem będziemy otrzymywali kopię całego zbioru, a nie tylko przeorganizowane elementy. Natomiast należy dodać, że struktury są wielokrotnie szybsze i dobrze używane mogą być stosowane przy optymalizacjach (np. oficjalna implementacja słownika łamie równie oficjalne zalecenia dotyczące struktur, aby uzyskać lepszą wydajność).

Podstawowe kwestie o strukturach:
https://msdn.microsoft.com/en-us/library/aa664471(VS.71).aspx

Wspomniane przez autora rekomendacje są zamieszczone w msdn:
https://msdn.microsoft.com/en-us/library/ms229017.aspx

Wątków w stylu struct vs class jest bardzo dużo, więc polecam poczytać. Osobiście korzystam ze struktur głównie przy obsłudze kodu niezarządzanego.

Offline kibiC++

  • Użytkownik

# Czerwiec 08, 2016, 14:51:28
Mógłbyś podać linka gdzie coś takiego wyczytałeś?

Z MSDN, dokładnie z drugiego linku podanego przez @strateg.

Wątków w stylu struct vs class jest bardzo dużo, więc polecam poczytać. Osobiście korzystam ze struktur głównie przy obsłudze kodu niezarządzanego.

Oczywiście czytałem :)

Głównie chodzi o mi o to, że skoro w C# nie mamy zbytniej kontroli nad tym gdzie obiekty są przechowywane to znaczy, że jest to jakoś optymalizowane 'wewnętrznie' i nie należy się tym zbytnio przejmować czy zwyczajnie świadomie zgadzamy się na siekanie cache'u w imię feature'ów języka :P

Ogółem wydawało mi się, że przejście z C++ na C# jest łagodniejsze. O ile składnia jest banalna to jednak człowiek wbił sobie do głowy pewne zachowania i przestawienie się nie jest takim hop-siup (value-semantic, const-correctness, etc. )

Offline lethern

  • Użytkownik

# Czerwiec 08, 2016, 15:07:04
Kibic, ale skoro masz unmanaged code, w którym możesz (choć nie bawiłem się w to, więc przypuszczam że) robić co chcesz, to czy nie umożliwia Ci to zrobienie krytycznego kodu w tym właśnie surowym c++ ? (w imię tego przysłowiowego "za 90% wydajności odpowiada 10% kodu")

wydaje się, że jak już przystałeś na Unity oraz C#, to zgodziłeś się na takie a nie inne rozmieszczenie danych w pamięci :P
« Ostatnia zmiana: Czerwiec 08, 2016, 15:12:28 wysłana przez lethern »

Offline ArekBal

  • Użytkownik

# Czerwiec 08, 2016, 21:28:09
Może powiedzmy sobie to że całe standardowe c# api(w tym linq) zostało napisane w większości wbrew strukturom(w tym Listy...).

Polecam koncentracje na strukturach i tego rodzaju optymalizacjach w kluczowych momentach. Efekty będą wymierne.

Aleee....
Kod będzie wyglądał jak C++ dla ubogich. Wymaga to sporo doświadczenia i wiedzy.

Offline strateg

  • Użytkownik

# Czerwiec 09, 2016, 13:26:48
ArekBal, możesz rozwinąć swoją myśl na temat słabego wykonania API w LINQ? (Odniosłem wrażenie negatywnej opinii na jego temat) Osobiście mnie sposób jego wykonania bardzo do siebie przekonał, a łatwość wywołania operacji wielowątkowych przy jego pomocy jest moim zdaniem genialna. No i nigdy nie narzekałem na wydajność, zazwyczaj stała na bardzo dobrym poziomie...

Offline kibiC++

  • Użytkownik

# Czerwiec 09, 2016, 23:11:42
wydaje się, że jak już przystałeś na Unity oraz C#, to zgodziłeś się na takie a nie inne rozmieszczenie danych w pamięci :P
No tak. Tylko to trochę zaburzyło mój światopogląd i stąd cały ten wątek :)

Może powiedzmy sobie to że całe standardowe c# api(w tym linq) zostało napisane w większości wbrew strukturom(w tym Listy...).
Z C# wącham się od niecałego tygodnia, więc jeszcze sporo przede mną... Nadal np. nie widzę sensu w podziale na field/property :P

Polecam koncentracje na strukturach i tego rodzaju optymalizacjach w kluczowych momentach. Efekty będą wymierne.
Zapisałem.

Aleee....
Kod będzie wyglądał jak C++ dla ubogich. Wymaga to sporo doświadczenia i wiedzy.
Dopóty będzie to twór hobbystyczny i jednoosobowy dopóki brzydki kod nie będzie raczej stanowił problemu. Gorzej z doświadczeniem i wiedzą :D

Aktualnie zastanawiam się jak mógłbym zarządzać sceną i wszelakimi obiektami i ich zależnościami bez wszędobylskich managerów do których mam jakąś wrodzoną awersje. Nie wspominając już o singletonach które są chyba nieodłącznym elementem każdego tutoriala do Unity :P



Offline ArekBal

  • Użytkownik

  • +2
# Czerwiec 13, 2016, 10:24:31
Jeśli dopiero zaczynasz to nic nie optymalizuj. NIC. :)


Offline koirat

  • Użytkownik

# Czerwiec 13, 2016, 11:06:21
@up w miare rozsadku. Np nie uzywaj brutforce kiedy jest inne proste rozwiazanie.

Offline deadeye

  • Użytkownik

# Czerwiec 15, 2016, 23:42:49
1.) Sporo można poczytać o efektywnym rozłożeniu danych ( hot/cold, cache-friendly, etc. ). Jak to się ma do architektury Unity skoro klasy w C# to typy referencyjne i jakiekolwiek grupowanie ich(jeśli takowe występuje) w tablice/listy to jedynie grupowanie referencji a same obiekty latają sobie gdzieś swobodnie po zakamarkach heapu?
AFAIK, Unity robi efektowne rozłożenie automatycznie, i to właśnie dzięki typom referencyjnym. Menadżer alokacji po prostu umieszcza obiekty tego samego typu w osobnych obszarach pamięci, jeden po drugim, w kolejności alokacji. Więc jeśli masz tysiąc klas Human, z których każda ma referencje na obiekt Gun, to pomimo że w konstruktorze Human tworzysz klasę Gun, w pamięci będziesz miał jedną "tablicę" obiektów Human i w innym miejscu tablicę obiektów Gun. I to niezależnie od tego, czy obiekty danego typu są u ciebie zadeklarowane jako np tablica, czy ich referencje i konstrukcje są porozrzucane w wielu niezależnych miejscach.

Cytuj
3.) W wielu miejscach można wyczytać, żeby struktury raczej omijać z daleka, a jeśli już jest taka potrzeba to:
  a.) powinny być nie większe niż 16b
  b.) powinny być niemutowalne
możesz pisać w miarę ładne TDD używająć struktur o dowolnej wielkości, jeśli przekazujesz struktury jako referencje, a nie kopie.  Np:
static void fun(ref MyStructType gun, int param)

W ten sposób masz kontrolę nad ułożeniem w pamięci, i nie dokonujesz zbędnych kopii w pamięci. Oczywiście przez takie rozwiązania kod jest o wiele mniej czytelny, na poziomie winapi.

Cytuj
4.) Czy zalecany maksymalny rozmiar struktur z pkt. 3a jest związany wyłącznie z tym, że structy przekazywane są przez wartość? Jeśli tak, to w czym problem przekazywać strukture przez ref?
tym, że zamiast wywoływać metody na stukturze, musisz mieć zestaw statycznych funkcji który przyjmuje strukturę. W ten sposób twój kod szybko staje się mniej czytelny. Poza tym wtedy strukturę przekazujesz przez referencje zawsze, żeby było szybciej, więc nie widzisz kiedy ta struktura jest przesyłana żeby coś odczytać, a kiedy żeby ją zmodyfikować. Normalnie przekazywanie przez ref odnosi się raczej do modyfikacji,a w takim designie nadmiarowo także do odczytu. Poza tym, jeśli stosujesz się do zasady immutable, to każda zmiana w strukturze wymusza stworzenie jej kopii, a to też nie jest czytelne ani miłe.


Podsumowując: słuchaj rady Arka :D


BTW spora część wydajności to rendering i fizyka, a te operacje są w unity napisane natywnie, i są zoptymalizowane pod kątem dd. Prawdopodobnie twój kod to tylko ~10% całości operacji, i choćbyś nawet napisał go w najwolniejszym języku to nie spowolni jakoś znacznie aplikacji. Przynajmniej dopóki czegoś nie zepsujesz :D

Offline laggyluk

  • Użytkownik
    • http://laggyluk.com

# Czerwiec 16, 2016, 17:31:24
moje trzy grosze: ze względu na GC czasem warto zrobić pool (basenik?) obiektów niż ciągle tworzyć i niszczyć

Offline kibiC++

  • Użytkownik

# Czerwiec 19, 2016, 14:05:20
AFAIK, Unity robi efektowne rozłożenie automatycznie, i to właśnie dzięki typom referencyjnym. Menadżer alokacji po prostu umieszcza obiekty tego samego typu w osobnych obszarach pamięci, jeden po drugim, w kolejności alokacji. Więc jeśli masz tysiąc klas Human, z których każda ma referencje na obiekt Gun, to pomimo że w konstruktorze Human tworzysz klasę Gun, w pamięci będziesz miał jedną "tablicę" obiektów Human i w innym miejscu tablicę obiektów Gun. I to niezależnie od tego, czy obiekty danego typu są u ciebie zadeklarowane jako np tablica, czy ich referencje i konstrukcje są porozrzucane w wielu niezależnych miejscach.
O taką odpowiedź mi chodziło :) Można gdzieś znaleźć więcej informacji o bebechach Unity?

tym, że zamiast wywoływać metody na stukturze, musisz mieć zestaw statycznych funkcji który przyjmuje strukturę. W ten sposób twój kod szybko staje się mniej czytelny. Poza tym wtedy strukturę przekazujesz przez referencje zawsze, żeby było szybciej, więc nie widzisz kiedy ta struktura jest przesyłana żeby coś odczytać, a kiedy żeby ją zmodyfikować. Normalnie przekazywanie przez ref odnosi się raczej do modyfikacji,a w takim designie nadmiarowo także do odczytu. Poza tym, jeśli stosujesz się do zasady immutable, to każda zmiana w strukturze wymusza stworzenie jej kopii, a to też nie jest czytelne ani miłe.
Faktycznie. Zapomniałem, że tu nie ma const z C++ :P

Podsumowując: słuchaj rady Arka :D
Na początek zapewne zastosuje się do rady ;) Ale, że nie zawsze w wolnych chwilach mam chęć na 'kodzenie' to zbieram info na co zwrócić uwagę i czego szukać po necie.

BTW spora część wydajności to rendering i fizyka, a te operacje są w unity napisane natywnie, i są zoptymalizowane pod kątem dd. Prawdopodobnie twój kod to tylko ~10% całości operacji, i choćbyś nawet napisał go w najwolniejszym języku to nie spowolni jakoś znacznie aplikacji. Przynajmniej dopóki czegoś nie zepsujesz :D
Pewnie dlatego Unity jest tak popularny. Ale czytałem ostatnio o IL2CPP który ponoć tłumaczy IL na C++ co daje dodatkowego kopa no i tak mnie naszło na rozmyślanie... :P