Model Polytope
Model wielościenny (zwany także metodą polytope ) jest matematyczną ramą dla programów, które wykonują dużą liczbę operacji — zbyt dużą, aby można ją było wyraźnie wyliczyć — co wymaga zwartej reprezentacji . Programy z zagnieżdżonymi pętlami są typowym, ale nie jedynym przykładem, a najczęstszym zastosowaniem tego modelu jest optymalizacja zagnieżdżenia pętli w optymalizacji programu . Metoda wielościanów traktuje każdą iterację pętli w zagnieżdżonych pętlach jako punkty siatki wewnątrz obiektów matematycznych zwanych wielościanami , wykonuje transformacje afiniczne lub bardziej ogólne transformacje nieafiniczne, takie jak kafelkowanie na polytopach, a następnie konwertuje przekształcone polytopy na równoważne, ale zoptymalizowane (w zależności od docelowego celu optymalizacji), zagnieżdżenia pętli poprzez skanowanie wielościanów.
Prosty przykład
Rozważmy następujący przykład napisany w C :
stała int n = 100 ; int ja , j , za [ n ][ n ]; dla ( ja = 1 ; ja < n ; ja ++ ) { dla ( jot = 1 ; jot < ( ja + 2 ) && jot < n ; jot ++
) { za [ ja ][ jot ] = za [ ja - 1 ][ jot ] + za [ ja ][ jot - 1 ]; } }
Podstawowy problem z tym kodem polega na tym, że każda iteracja wewnętrznej pętli na a[i][j]
wymaga, aby wynik poprzedniej iteracji, a[i][j - 1]
, był już dostępny. W związku z tym tego kodu nie można zrównoleglać ani przesyłać potokowo, tak jak jest obecnie napisany.
Zastosowanie modelu polytope z transformacją afiniczną i odpowiednia zmiana granic przekształci powyższe zagnieżdżone pętle w:
za [ ja - jot ][ jot ] = za [ ja - jot - 1 ][ jot ] + za [ ja - jot ][ jot - 1 ];
W tym przypadku żadna iteracja pętli wewnętrznej nie zależy od wyników poprzedniej iteracji; cała wewnętrzna pętla może być wykonywana równolegle. (Jednak każda iteracja pętli zewnętrznej zależy od poprzednich iteracji).
Szczegółowy przykład
Poniższy kod C implementuje formę ditheringu dystrybucji błędów podobną do ditheringu Floyda-Steinberga , ale zmodyfikowaną ze względów pedagogicznych. Dwuwymiarowa tablica src
zawiera h
wierszy po w
pikseli, przy czym każdy piksel ma wartość w skali szarości z zakresu od 0 do 255 włącznie. Po zakończeniu procedury tablica wyjściowa dst
będzie zawierać tylko piksele o wartości 0 lub 255. Podczas obliczeń błąd ditheringu każdego piksela jest zbierany przez dodanie go z powrotem do src
szyk. (Zauważ, że src
i dst
są zarówno odczytywane, jak i zapisywane podczas obliczeń; src
nie jest tylko do odczytu, a dst
nie jest tylko do zapisu).
Każda iteracja pętli wewnętrznej modyfikuje wartości w src[i][j]
na podstawie wartości src[i-1][j]
, src[i][j-1]
i src[i+1][ j-1]
. (Te same zależności dotyczą dst[i][j]
. Na potrzeby pochylenia pętli możemy myśleć o src[i][j]
i dst[i][j]
jako o tym samym elemencie). zależności src[i][j]
graficznie, jak na diagramie po prawej stronie.
0
0 #define ERR(x, y) (dst[x][y] - src[x][y]) void dither ( unsigned char ** src , unsigned char ** dst , int w , int h ) { int i , j ; dla ( jot = ; jot < godz ; ++ jot ) { za ( ja = ; ja <
0
0
w ; ++ ja ) { int v = źródło [ ja ][ j ]; jeśli ( i > ) v -= BŁĄD ( i - 1 , j ) / 2 ; jeśli ( j > ) { v -= BŁĄD ( ja , j - 1 ) / 4 ;
0
0 jeśli ( i < w - 1 ) v -= BŁĄD ( i + 1 , j - 1 ) / 4 ; } dst [ ja ][ jot ] = ( v < 128 ) ? : 255 ; źródło [ ja ][ jot ] = ( v < ) ? 0
: ( v < 255 ) ? w : 255 ; } } }
|
Wykonanie transformacji afinicznej na oryginalnym diagramie zależności daje nam nowy diagram co widać na kolejnym obrazku. Możemy następnie przepisać kod, aby zapętlił się na p
i t
zamiast i
i j
, uzyskując następującą „skośną” procedurę.
0
void dither_skewed ( unsigned char ** src , unsigned char ** dst , int w , int h ) { int t , p ; dla ( t = ; t < ( w + ( 2 * godz )); ++ t ) { int min = maks (
t % 2 , t- ( 2 * h ) + 2 ) ; int pmax = min ( t , w - 1 ); dla ( p = pmin ; p <= pmax ; p += 2 ) { int ja = p ; int j = ( t -
0
0
p ) / 2 ; int v = źródło [ i ][ j ]; jeśli ( i > ) v -= BŁĄD ( i - 1 , j ) / 2 ; jeśli ( j > ) v -= BŁĄD ( ja , j - 1 ) / 4 ; jeśli ( 0
0
0 j > && ja < w - 1 ) v -= BŁĄD ( ja + 1 , j - 1 ) / 4 ; dst [ ja ][ jot ] = ( v < 128 ) ? : 255 ; źródło [ ja ][ jot ] = ( v < ) 0
? : ( v < 255 ) ? w : 255 ; } } }
|
Zobacz też
- Ramy wspierające model wielościenny
- Optymalizacja gniazda pętli
- Optymalizacja pętli
- Rozwijanie pętli
- Kafelkowanie w pętli
Zewnętrzne linki i odnośniki
- „Podstawowa metoda polytope” , samouczek Martina Griebla zawierający diagramy powyższego przykładu pseudokodu
- „Generowanie kodu w modelu Polytope” (1998). Martina Griebla, Christiana Lengauera i Sabine Wetzel
- „Generator kodu wielościennego CLooG”
- „CodeGen+: skanowanie wielościanów Z” [ stały martwy link ]
- PoCC: kolekcja kompilatorów wielościennych
-
PLUTO - automatyczny równoległość i optymalizator lokalizacji dla gniazd pętli afinicznych
- Bondhugula, Uday; Hartono, Albert; Ramanujam, J.; Sadayappan, P. (2008-01-01). Praktyczny automatyczny paralelizator wielościenny i optymalizator lokalizacji . Materiały z 29. Konferencji ACM SIGPLAN na temat projektowania i wdrażania języka programowania . PLDI '08. Nowy Jork, NY, USA: ACM. s. 101–113. doi : 10.1145/1375581.1375595 . ISBN 9781595938602 . S2CID 7086982 .
- polyhedral.info - Strona internetowa zbierająca informacje o kompilacji wielościanów
- Polly — platforma LLVM do optymalizacji pętli wysokiego poziomu i lokalizacji danych
- MIT Tiramisu .