2009-07-15 11 views
5

Szukam, co programista może zrobić w C, który może określić wydajność i/lub rozmiar wygenerowanego pliku obiektu.Praktyki kodowania C dla wydajności lub rozmiaru kodu - poza tym, co kompilator robi

Dla np,
1. Deklarowanie proste get/set funkcje jak inline może zwiększyć wydajność (kosztem większej footprint)
2. Do pętli, które nie korzystają z wartości samej zmiennej pętli, count do zera zamiast liczenia do pewnej wartości itd.

Wygląda na to, że kompilatory przeszły teraz do takiego poziomu, że "proste" sztuczki (jak dwa powyższe punkty) wcale nie są wymagane. Odpowiednie opcje podczas kompilacji i tak wykonają zadanie. Heck, widziałem także posty o tym, jak kompilatory obsługują rekurencję - to było bardzo interesujące! Więc co mamy zrobić na poziomie C? :)

Moje specyficzne środowisko to: GCC 4.3.3 ponownie ukierunkowane na architekturę ARM (v4). Ale reakcje na innych kompilatorach/procesorach są również mile widziane i będą nabierać ochoty.

PS: To podejście jest sprzeczne ze zwykłym "code first !, a następnie benchmarkem i ostatecznie optymalizacji" podejście.

Edit: Podobnie jak zdarza się tak, znalazłem podobne stanowisko po zaksięgowaniu pytanie: Should we still be optimizing "in the small"?

+0

http://stackoverflow.com/questions/110684/what-coding-techniques-do-you-use-for-optimising-c-programs http://stackoverflow.com/questions/178045/when- powinieneś zacząć-optymalizacji-kod # 178079 http://stackoverflow.com/questions/242149/when-should-i-optimize –

+0

Co jest nie tak ze zwykłym "kod pierwszy !, a następnie test porównawczy, a na końcu optymalizacji" podejście? –

+0

Nic w tym złego - powinno to być sposób optymalizacji. Moją motywacją jest sprawdzenie, czy mogę zaimplementować narzędzie do refaktoryzacji kodu (po profilowaniu), aby pomóc programistce szybko zmienić wydajność i/lub obszar. Wyobraź sobie plugin Eclipse (lub skrypt vim), który podkreśla pętle i daje opcje do powiedzenia, rozwinąć je lub zmienić wewnętrzną i zewnętrzną pętlę. Powinienem to wyjaśnić w poście, przepraszam za to. Dzięki za linki! –

Odpowiedz

6

Jedno mogę myśleć, że kompilator prawdopodobnie nie będzie optymalizacja jest „skrzynka obsługi”: Jeśli robisz iterację na dwuwymiarowej tablicy w rządowej kolejności, powiedz, upewnij się, że twoja wewnętrzna pętla biegnie przez indeks kolumny, aby uniknąć rzucania pamięci podręcznej. Posiadanie wewnętrznej pętli uruchomionej na niewłaściwym indeksie może spowodować ogromny wzrost wydajności.

Dotyczy to wszystkich języków programowania, ale jeśli programujesz w języku C, wydajność ma dla Ciebie kluczowe znaczenie, dlatego jest szczególnie istotna.

+0

Procesory AFAIK ARM v4 nie mają pamięci podręcznej. – starblue

+0

Zależy ... niektórzy członkowie rodziny, niektórzy nie. (http://en.wikipedia.org/wiki/ARM_architecture) –

5

"Zawsze" zna złożoność czasową i przestrzenną algorytmów. Kompilator nigdy nie będzie w stanie wykonać tej pracy tak dobrze, jak tylko możesz. :)

1

PreComputation, gdzie to możliwe ... (przepraszam, ale nie zawsze jest to możliwe ... Zrobiłem obszerne prekomputacje na moim silniku szachowym.) Przechowuj te wyniki w pamięci, mając na uwadze pamięć podręczną. Im większy rozmiar precomputation dane w pamięci mniejsze szanse na zrobienie trafienia w pamięci podręcznej. Ponieważ większość najnowszego sprzętu jest wielordzeniowym, możesz zaprojektować aplikację, aby ją skierować.

jeśli używasz kilka dużych tablic upewnij się grupować je blisko siebie, gdzie będą one wykorzystane, zwiększając pamięć podręczną uderza

3

Kompilatory te dni nadal nie są bardzo dobre na Wektoryzacja swój kod tak was” Nadal chcę przeprowadzić implementację większości algorytmów SIMD.

Wybór odpowiednich struktur danych dla dokładnego problemu może znacznie zwiększyć wydajność (widziałem przypadki, w których przejście z drzewa Kd do BVH spowodowałoby to w tym konkretnym przypadku).

Kompilatory mogą wstawić niektóre elementy/zmienne w celu dopasowania do pamięci podręcznej, ale inne optymalizacje pamięci podręcznej, takie jak lokalizacja danych, pozostają w gestii użytkownika.

Kompilatory nadal nie powodują, że twój kod jest wielowątkowy, a korzystanie z OpenMP, z mojego doświadczenia, nie pomaga zbytnio.(Naprawdę musisz zrozumieć OpenMP, aby znacznie zwiększyć wydajność). Więc obecnie jesteś sam, robiąc wielowątkowość.

2

Aby dodać do tego, co mówi Martin powyżej około cache obsługi:

  • zamianom swoje struktury takie, że pola, które są najczęściej komunikuje razem są w tej samej linii pamięci podręcznej może pomóc (na przykład poprzez ładowanie tylko jeden cache linii zamiast dwóch). W ten sposób zwiększasz gęstość użytecznych danych w pamięci podręcznej danych. Istnieje narzędzie linuksowe, które może ci w tym pomóc: krasnoludy 1. http://www.linuxinsight.com/files/ols2007/melo-reprint.pdf

  • możesz użyć podobnej strategii, aby zwiększyć gęstość kodu. W gcc możesz oznaczać gorące i zimne gałęzie za pomocą tagów prawdopodobnych/mało prawdopodobnych. Dzięki temu gcc może przechowywać zimne gałęzie oddzielnie, co pomaga zwiększyć gęstość icache.

A teraz coś z zupełnie innej beczki:

  • dla pól, które mogą być dostępne (czytaj i pisemne) w całej procesorów, przeciwnie strategia ma sens. Problem polega na tym, że dla celów spójności tylko jeden procesor może mieć możliwość zapisu na ten sam adres (w rzeczywistości ta sama pamięć podręczna). Może to prowadzić do stanu zwanego ping-pong w pamięci podręcznej. Jest to bardzo złe i może być gorsze, jeśli linia pamięci podręcznej zawiera inne niepowiązane dane. W tym przypadku sensowne jest dopełnienie tych rywalizujących danych do długości linii pamięci podręcznej.

Uwaga: są to oczywiście mikro-optymalizacje, które można wykonać tylko na późniejszych etapach, gdy próbujesz wykręcić ostatnie fragmenty wydajności z kodu.

0

Wiele osób nie zdaje sobie z tego sprawy: Zdefiniuj etykietę wbudowaną (zależną od kompilatora), co oznacza, że ​​zgodnie z intencją - wiele kompilatorów umieszcza słowo kluczowe w zupełnie innym kontekście niż pierwotne znaczenie. Istnieją również sposoby na zwiększenie wbudowanych limitów rozmiaru, zanim kompilator zacznie wyrzucać trywialne rzeczy z linii. Liniowanie w sposób ukierunkowany przez człowieka może generować znacznie szybszy kod (kompilatory są często konserwatywne lub nie stanowią wystarczającej ilości programu), ale musisz nauczyć się go poprawnie używać, ponieważ może on (łatwo) przynieść efekt przeciwny do zamierzonego. I tak, to absolutnie dotyczy zarówno rozmiaru kodu, jak i prędkości.