Post on 14-Feb-2021
Programowanie Równoległewykład 13
Symulacje komputerowe cieczy
LBM w CUDA
Maciej Matyka
Instytut Fizyki Teoretycznej
Transport cieczy i gazów
• W wielu dziedzinach trzeba rozwiązać zagadnienie
transportu cieczy lub gazów
– aerodynamika
• opływ (np. samochodów
• sport
– biologia i medycyna
• przepływy w naczyniach
krwionośnych
• próby przewidzenia
• miejsc narażonych na deformacje
– technika
• transport w ośrodkach porowatych
• problemy optymalizacji
– przewidywanie pogody
– etc.
Metody rozwiązania
• Navier–Stokes Equations (NSE)
• Smoothed Particle Hydrodynamics (SPH)
• Dissipative Particle Dynamics (DPD)
• The Lattice Boltzmann Method (LBM)
• Lattice Gas Automata (LGA)
• Molecular Dynamics (MD)
Skala makro (continuum)
Skala mikro (poziom atomowy)
Metody rozwiązania
• Navier–Stokes Equations (NSE)
• Lattice Gas Automata (LGA)
• Molecular Dynamics (MD)
Skala makro (continuum)
Skala mikro (poziom atomowy)
Równania Naviera--Stokesa
• Równania Naviera-Stokesa dla cieczy nieściśliwej:
• Nieliniowe równanie różniczkowe drugiego rzędu
• + równanie ciągłości (gęstość stała)
http://en.wikipedia.org/wiki/Navier-Stokes equations
Rozwiązywanie równań NS
• Linearyzacja do postaci Ax=B
– Metody: FDM, FVM, FEM
– rozwiązanie układu równań liniowych (np. metody iteracyjne)
• Problemy:
– Problem nieliniowy zamieniamy na problem liniowy
– Stabilność / dokładność / istnienie rozwiązania
– Czas obliczeń
– Skala w zasadzie tylko continuum
– Złożoność algorytmów i podatność na błędy (zadanie w zasadzie na lata)
Dynamika molekularna
• Ogromna ilość atomów
• równania ruchu
• oddziaływanie atomu z atomem
• Skala mikroskopowa
• Potencjał L-J
Allen, M.P et al., ”Computer Simulation of Liquids”, Oxford Univ. Press.
Model gazu sieciowego LGA
• Najbardziej znanym modelem gazu sieciowego jest
opisany przez U. Frisha, B. Hasslachera iY. Pomeau
gaz FHP
Rys. Kolizje w modelu FHP5
• Transport
• Kolizje
U. Frish, B. Hasslacher, Y. Pomeau 1986 Lattice-Gas Automata for theNavier-Stokes Equation, Phys. Rev. Lett. 56, 1505–1508.
LGA w praktyce
• Praca magisterska:
Sebastian Szkoda, „Implementacja modelu FHP w technologii NVIDIA CUDA”
http://www.ift.uni.wroc.pl/~sebastian.szkoda/Seb
astianSzkoda_MSc.pdf
• Implementacja przez podział przestrzenny z komunikacją
Porównanie FHP3 do doświadczenia MPI Bremen)
Przyspieszenie względem CPU
Model gazu sieciowego LGA
• Problemy
– szum statystyczny
– wymaga uśredniania w czasie
– wymaga uśredniania w przestrzeni
– wymaga dużych siatek (pamięć)
Metoda gazu sieciowego Boltzmanna
• Historycznie wprowadzona jako rozwinięcie LGA
• Zmienne ni (0,1) zamienione na funkcje rozkładu
Popularność LBM
• Artykuły w PRE / PRL wspominające o metodzie Boltzmanna
• czasopisma najbardziej znane dla nas – fizyków
• Wybór sposobu szukania – tendencyjny, ale rezultat o czymś mówi…
Funkcja rozkładu
• Funkcja rozkładu jest zdefiniowana jako liczba
cząsteczek w skończonym elemencie przestrzeni
pędów i położeń:
• Zadaniem teorii kinetycznej jest znalezienie funkcji
dystrybucji dla zadanych oddziaływań
międzycząsteczkowych.
Równanie Boltzmanna
• Ewolucja czasowa funkcji rozkładu jest opisana
przez równanie Boltzmanna:
• Założenia :
– molekularny chaos (brak korelacji między prędkością, a położeniem cząsteczek)
– uwzględnienie tylko kolizji dwuciałowych
Przybliżenie BGK
• Człon kolizji, przybliżenie BGK (Bhatnagar, Gross,
Krook (1954)):
• Liniowa relaksacja do stanu równowagi feq
• feq wyznaczana np. z rozkładu Macwella-
Boltzmanna
Uwaga: istnieją bardziej zaawansowane modele kolizji o lepszych
właściwościach np. MRT
• Dyskretyzacja i model LBM
• Wprowadźmy dyskretne wektory prędkości i funkcję
rozkładu:
f ------> fi
v ------> ci
Model d2q9
Thorne, D., Sukop, M., ”Lattice Boltzmann Method for the Elder Problem”, FIU, CMWR(2004)
Wielkości makroskopowe
• Prędkości i gęstość wyznaczmy przez sumowanie
funkcji rozkładu:
• Gęstość:
• Prędkość:
Równanie transportu (dyskretnie)
• Równanie transportu w modelu sieciowym LBM:
• gdzie zakres i zależy od użytej sieci.
• t=0
Krok transportu
Krok transportu
• t=1/4
Krok transportu
• t=1/2
Krok transportu
• t=3/4
Krok transportu
• t=1
Krok Transportu - Implementacja
• Implementacja kroku transportu:
void propagatelbm(int _nx, int _ny, int curr)
{
int prev = 1 - curr;
for(i=0; i < _nx ; i++)
for(j=0; j < _ny ; j++)
if(F[ j * _nx + i ] & C_FLD)
{
for(k=0; k< 9; k++)
{
ip = i+ex[k];
jp = j+ey[k];
if( F[ jp * _nx + ip ] & C_BND )
{
df [curr][ jp * _nx + ip ][inv[k]] =
df [prev][ j * _nx + i ][k];
}
else
{
df [curr][ jp * _nx + ip ][k] =
df[prev][ j * _nx + i ][k];
}
}
}
Funkcja rozkładu w równowadze
• Lokalną funkcję rozkładu w równowadze zwykle
wyznacza się z rozwinięcia funkcji rozkładu
Maxwella-Boltzmanna [1]:
• gęstość płynu
• prędkość dźwięku dla sieci
• współczynniki wagowe sieci
• macierz jednostkowa
[1] S. Succi, O. Filippova, G. Smith, E. Kaxiras Applying the LatticeBoltzmann Equation to
MultiscaleFluid Problems, Comp. Sci. Eng., Nov-Dec 2001, 26–36
Kolizje - Implementacja
• Wyznaczanie członu kolizji:
(...)
for(k=0; k< 9; k++)
{
f0 = w[k] * rho *
(1.0 - (3.0/2.0) * (ux*ux + uy*uy)
+ 3.0 * (ex[k] * ux + ey[k]*uy)
+ (9.0/2.0) * (ex[k] * ux + ey[k]*uy) * (ex[k] * ux
+ ey[k]*uy));
df [curr][ j * _nx + i ][k] =
(1-omega) * df[curr][ j * _nx + i ][k] + omega*f0;
}
(omega = 1/tau)
Warunki brzegowe
[2] Succi, Sauro (2001). The Lattice Boltzmann Equation for Fluid
Dynamics and Beyond. Oxford University Press
• Bounce-back na sztywnej ściance
• Można uzyskać dokładność 2 rzędu stosując wersję
„mid-grid”, szczegóły [2]
Warunki brzegowe
• Bounce-back na sztywnej ściance
• Można uzyskać dokładność 2 rzędu stosując wersję
„mid-grid”, szczegóły [2]
[2] Succi, Sauro (2001). The Lattice Boltzmann Equation for Fluid
Dynamics and Beyond. Oxford University Press
Warunki brzegowe
• Bounce-back na sztywnej ściance
• Można uzyskać dokładność 2 rzędu stosując wersję
„mid-grid”, szczegóły [2]
[2] Succi, Sauro (2001). The Lattice Boltzmann Equation for Fluid
Dynamics and Beyond. Oxford University Press
Kolizje + transport w jednym kroku
• Kolizje i transport mogą być umieszczone w pojedynczym wyrażeniu
• Można powiedzieć, że poniższy kod to pełny algorytm LBM (bez kilku detali ) !for(int k=0; k< 9; k++)
{
int ip = ( i+ex[k] + L ) % (L);
int jp = ( j+ey[k] + L ) % (L);
// collision + streaming
if( FLAG[ip+jp*L] == 1 )
df [1-c][ i+j*L ][inv[k]] = (1-omega) *
df[c][ i+j*L ][k] + omega* w[k] * rho *
(1.0f - (3.0f/2.0f) * (ux*ux + uy*uy) +
3.0f * (ex[k] * ux + ey[k]*uy) +
(9.0f/2.0f) * (ex[k] * ux + ey[k]*uy) *
(ex[k] * ux + ey[k]*uy));
else
df [1-c][ip+jp*L][k] = (1-omega) * df[c][
i+j*L ][k] + omega* w[k] * rho * (1.0f -
(3.0f/2.0f) * (ux*ux + uy*uy)+ 3.0f * (ex[k] * ux
+ ey[k]*uy) + (9.0f/2.0f) * (ex[k] * ux +
ey[k]*uy) * (ex[k] * ux + ey[k]*uy));
}
Podsumowanie algorytm LBM
Najbardziej podstawowy model LBM składa się z
dwóch kroków:
• Krok kolizji:
• Krok transportu:
LBM na CUDA
• LBM nadaje się bardzo dobrze do urównoleglenia
• Operacje w algorytmie LBM:
– Wyznaczenie wielkości makroskopowych (lokalna)
– Wyznaczenie funkcji rozkładu (lokalna)
– Krok propagacji (nielokalna!):
1) podział sieci na podsieci (jak w pracy S. Szkody)
– Problem: wymaga komunikacji
2) użycie drugiej siatki (propagacja ping-pong)
– Problem: wymaga więcej pamięci
Jak przepisać LBM na CUDA?
• Start: gpu2d.zip (strona wykładu)
– alokuje pamięć na host (malloc)
– alokuje pamięć na gpu (cudaMalloc)
– wywołuje kernel CUDA przekazując wskaźnik
na pamięć urządzenia jako argument
– kopiuje dane z pamięci gpu->cpu
– zapisuje skopiowane dane jako rysunek .ppm (dołączony)
__global__ void Trace(float3 *IMG)
{
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
if(x*H + y>=W*H) return;
IMG[x*H + y].x = float(x)/float(W);
IMG[x*H + y].y = float(y)/float(H);
IMG[x*H + y].z = float(x+y)/float(W+H);
}
Jak przepisać LBM na CUDA?
• lbm-cpu.zip (strona wykładu)
• Zwięzła implementacja LBM na CPU
• Adwekcja cząstek przez pole prędkości
Kroki do wykonania
• Aby zaimplementować tę wersję LBM na CUDA
należy (wersja z dodatkową pamięcią):
1. zmienić strukturę funkcji rozkładu (np. tablice 1d)
// df on the device
float * c0f0; float * c0f1; float * c0f2; float * c0f3;
float * c0f4; float * c0f5; float * c0f6; float * c0f7;
float * c0f8; float * c1f0; float * c1f1; float * c1f2;
float * c1f3; float * c1f4; float * c1f5; float * c1f6;
float * c1f7; float * c1f8;
(…)
cudaMalloc(&c0f0, _nx*sizeof(float) * _ny * nz);
cudaMalloc(&c0f1, _nx*sizeof(float) * _ny * nz);
cudaMalloc(&c0f2, _nx*sizeof(float) * _ny * nz);
cudaMalloc(&c0f3, _nx*sizeof(float) * _ny * nz);
cudaMalloc(&c0f4, _nx*sizeof(float) * _ny * nz);
(…)
Kroki do wykonania
2. Zamiplementować kernel kolizji:
__global__ void deviceCollision(float *f0, float *f1,float *f2, float *f3,
float *f4, float *f5, float *f6, float *f7, float
*f8, int width, int height, int depth,
float *U, float *V, int *F)
{
int i = blockIdx.x * blockDim.x + threadIdx.x;
int j = blockIdx.y * blockDim.y + threadIdx.y;
(…) // kod jak w wersji CPU z małymi modyfikacjami
// wynikającymi głównie z nowego formatu funkcji rozkładu
}
Kroki do wykonania
3. Zamiplementować kernel transportu:
__global__ void devicePropagate(
float *fromf0, float *fromf1,float *fromf2, float *fromf3, float
*fromf4, float *fromf5, float *fromf6,float *fromf7, float *fromf8,
float *tof0, float *tof1,float *tof2, float *tof3, float *tof4,
float *tof5, float *tof6,float *tof7, float *tof8,
int width, int height, int depth, float *U, float *V, int *F)
{
int i = blockIdx.x * blockDim.x + threadIdx.x;
int j = blockIdx.y * blockDim.y + threadIdx.y;
(…)
// kod jak na CPU z jawnie
// wypisanym transportem wg formatu funkcji gęstości
// jak w preabule kernela
}
Schemat działania
1. Inicjalizuj dane (CPU)
2. Inicjalizuj dane (CPU -----> GPU)
3. W pętli:
a) Wywołuj kernel kolizji (CUDA)
b) Wywołuj kernel transportu (CUDA)
c) Przesuń cząstki po polu prędkości w nowe położenia
- To też można urównoleglić -> pierwszy wykład z CUDA!
d) Narysuj cząstki na ekranie
Przykład działania LBM na CUDA
• 512 x 512
• CPU stoi…. gdy w tym czasie GPU….
prg/lbm-cuda.exeprg/lbm-cpu.exe
Skalowanie
• LBM dało się szybko (dzień pracy) przyspieszyć
około 100 razy
• Można przyspieszyć jeszcze bardziej (wiele prac)
• Klastrów obliczeniowych nie da się jeszcze przebić
(pamięć, skala obliczeń) – multi GPU ?
• Mniejsze zastosowania „osobiste” – tu jak
najbardziej CUDA ma sens
CPU
_tim
e/
GPU
_tim
e
L
fin
Literatura
• S. Succi, The Lattice Boltzmann Equation for Fluid
Dynamics and Beyond., Oxford University Press
(2001)
• U. Frish, B. Hasslacher, Y. Pomeau 1986 Lattice-Gas
Automata for the Navier-Stokes Equation, Phys. Rev.
Lett. 56, 1505–1508.
• G.R. McNamara, G. Zanetti Use of the Boltzmann
Equation to Simulate Lattice-Gas Automata, Phys.
Rev. Lett. 61(20), 2332–2335.
• S. Succi, O. Filippova, G. Smith, E. Kaxiras Applying
the Lattice Boltzmann Equation to Multiscale Fluid
Problems, Comp. Sci. Eng., Nov-Dec 2001, 26–36.