6 апреля 2010 Использование CUDA в расчете динамики пучка С.Б. Ворожцов, В.Л. Смирнов, Е.Е. Перепелкин Дубна, ОИЯИ http://parallel-compute.ru Циклотрон • Постановка задачи • Численные методы • Программная реализация на CUDA • Результаты http://cbda.jinr.ru CBDA: Cyclotron Beam Dynamic Analysis code Постановка задачи Компьютерная модель циклотрона Линия инжекции Инфлектор Дуант ЭСД Магнитный сектор Области задания карт полей Инфлектор Электрическое поле Аксиальный канал Магнитное поле Линза Магнитное поле Ресурсоемкое моделирование • Необходимость рассмотреть не менее 5 различных конфигураций центральной зоны; • Необходимость ускорять различные ионы; • Сложная геометрическая структура; • Учет пространственного заряда; Одна итерация требует ~ несколько дней расчетов Уравнения движения ri , pi , t , i 1 N d pi Fi , i 1 N dt d mi dt i vi qi Eext ri , t Es ri , t vi , Bext ri 1 1 2 , vi i i i c 0 0 0 0 r r , v v , или r r , v v i t ti i i t ti i i t 0 i i t 0 i 1 i N , ri V Пространственный заряд divEs , 0 rotEs Bs , t rotBs 0 J s divBs 0, PIC метод 1 Es 2 c t 1 0 0 c2 PP метод Es p p , p 0 , , D N D N D n N Es ri N 1 4 0 Es j i j i 1 qj ri rj qj 4 0 R3 3 r r , i r r , i j j i 1 N ri rj R Численные методы Уравнение движения Уравнение движения из постановки задачи d mi i vi qi Eext ri , t Es ri , t vi , Bext ri , i 1, dt ,N можно представить в упрощенном виде, дополнив его вторым уравнением для определения координат частиц dvi dt f t , ri , vi dri v i dt 0 vi v i t t0 0 ri t t0 ri Пример решения ОДУ Рассмотрим решение обыкновенного дифференциального уравнения (ОДУ) методом Рунге -Кутта Задача Коши dx dt f t , x x x0 t t 0 k номер итерации по времени , шаг по времени xk 1 xk kx 6 1 2 kx2 2 kx3 kx4 kx1 f tk , xk kx1 kx2 f tk , xk 2 2 kx2 kx3 f tk , xk 2 2 kx4 f tk , xk kx3 Метод Рунге - Кутта vxk 1 vxk vyk 1 vyk vzk 1 vzk kvx 6 2 kvx2 2 kvx3 kvx4 kvy 6 1 2 kvy2 2 kvy3 kvy4 1 2 kvz2 2 kvz3 kvz4 1 kvz 6 kx 6 xk 1 xk 1 2 kx2 2 kx3 kx4 ky 6 2 ky2 2 ky3 ky4 2 kz2 2 kz3 kz4 yk 1 yk zk 1 zk 1 kz 6 1 Метод Рунге - Кутта kx1 vx tk , xk , yk , zk , vxk , vyk , vzk ky1 , kz1 kvx1 f x tk , xk , yk , zk , vxk , vyk , vzk kvy , kvz 1 1 kx1 ky1 kz1 kvx1 kvy1 kvz1 kx v t , x , y , z , vx , vy , vz x k k k k k k k 2 2 2 2 2 2 2 2 ky2 , kz2 kvx f t , x kx1 , y ky1 , z kz1 , vx kvx1 , vy kvy1 , vz kvz1 x k k k k k k k 2 2 2 2 2 2 2 2 kvy2 , kvz2 Метод Рунге - Кутта kx2 ky2 kz2 kvx2 kvy2 kvz2 kx v t , x , y , z , vx , vy , vz x k k k k k k k 3 2 2 2 2 2 2 2 ky3 , kz3 kvx f t , x kx2 , y ky2 , z kz2 , vx kvx2 , vy kvy2 , vz kvz2 x k k k k k k k 3 2 2 2 2 2 2 2 kvy3 , kvz3 kx4 vx tk , xk kx3 , yk ky3 , zk kz3 , vxk kvx3 , vyk kvy3 , vzk kvz3 ky4 , kz4 kvx4 f x tk , xk kx3 , yk ky3 , zk kz3 , vxk kvx3 , vyk kvy3 , vzk kvz3 kvy , kvz 4 4 Решение краевой задачи p , p 0 0 p При поиске коэффициентов Фурье используется алгоритм БПФ (Быстрого Преобразования Фурье) xi , y j , zs необходимо найти из распределения частиц 8 n, m, k Nx N y Nz ni mj ks xi , y j , zs sin sin sin N N N i 1 x y z N z 1 N y 1 N x 1 s 1 j 1 n 2 m 2 k 2 n, m, k n, m, k Lx Ly Lz ( xi , y j , zs ) ni mj ks n, m, k sin sin sin N N N n 1 x y z N z 1 N y 1 N x 1 k 1 m 1 1 Задание области для краевой задачи Lz Lz Lx Lx Ly Lx Lz Ly Сетка Nx Ny Nz Ly Шаг hx Lx Ly Lz , hy , hz Nx Ny Nz Раздача плотности заряда Ячейка 7 Ячейка 8 Узел Ячейка 6 Ячейка 5 Ячейка 3 Ячейка 2 Ячейка 1 Потери частиц B D tn+1 A C tn Если точка D принадлежит треугольнику ABC, тогда SADC SADB SCDB SABC Условие пересечения SADC SADB SCDB SABC где εΔ – допустимое отклонение от поверхности Программная реализация на CUDA Функции ядра • Track ( карты полей, координаты и скорости частиц ) • метод Рунге-Кутта • Losses ( геометрия установки, координаты частиц ) • проверка пересечений с геометрией • Rho ( координаты частиц ) • раздача заряда в узлы сетки • FFT ( функция плотности заряда или потенциал) • БПФ по базисным функциям sin(πn/N) • PoissonSolver ( Фурье коэффициенты ) • решение краевой задачи • E_SC ( потенциал электрического поля ) • поиск электрического поля __global__ void Track ( ) • Много входных параметров. Использование типа переменной __constant__ для неизменных параметров: • __device__ __constant__ float d_float[200]; • __device__ __constant__ int d_int[80]; • Каждой частице соответствует нить: • int n = threadIdx.x+blockIdx.x*blockDim.x; • Количество “if, goto, for” необходимо максимально сократить Проблема количества “if, goto, for” Инфлектор Электрическое поле Аксиальный канал Магнитное поле Линза Магнитное поле __global__ void Losses ( ) • Нити одного блока копируют вершины треугольников из global в shared память. • Синхронизация нитей после копирования треугольников __syncthreads() • Каждой частице соответствует номер нити: • int n = threadIdx.x+blockIdx.x*blockDim.x; • Проверка условия пересечения частицей c номером n, загруженных в shared память, треугольников • Для каждого блока геометрии есть своя функция Losses __global__ void Rho • Каждая частица с номером n = threadIdx.x + blockIdx.x*blockDim.x дает свой вклад, в окружающие ее узлы. Для этого по координатам частицы определяется какой ячейки она принадлежит • Одна частица может дать вклад в 8 ближайших узлов. Таким образом, каждая нить заполняет свои 16 ячеек в общем массиве вклада: 8 – номеров узлов и 8 – значений вклада. • Далее производится сложение этих вкладов для каждого узла. __global__ FFT ( ) • Действительное БПФ по базисным функциям sin(πn/N); • 3D преобразование состоит из трех последовательных 1D БПФ по осям: X, Y, Z соответственно • int n = threadIdx.x+blockIdx.x*blockDim.x; k=(int)(n/(NY+1)); j=n-k*(NY+1); m=j*(NX+1)+k*(NX+1)*(NY+1); FFT_X[i+1]=Rho[i+m]; n = j + k*(NY+1) NY NZ Массив данных для функции Rho трех переменных __global__ PoissonSolver ( ) • Номер нити int n = threadIdx.x+blockIdx.x*blockDim.x; • Каждая нить находит значение коэффициентов Фурье PhiF потенциала Phi PhiFind(i,j,k) = -RhoFind(i,j,k) / ( kxi2 + kyj2 + kzk2 ) В узле с номером: ind(i,j,k)=i+j*(NX+1)+k*(NX+1)*(NY+1), где k=(int)(n/(NX+1)*(NY+1)); j=(int)(n-k*(NX+1)*(NY+1))/(NX+1); i=n-j*(NX+1)-k*(NX+1)*(NY+1); • RhoF – коэффициенты Фурье для функции плотности заряда Rho. __global__ E_SC ( ) • Вычисление электрического поля в узле с номером int n = threadIdx.x+blockIdx.x*blockDim.x+st_ind φn + ( NX + 1 )( NY + 1 ) φn - 1 φn Ex φn + ( NX + 1 ) Ey Ez φn - ( NX + 1 ) φn + 1 φn - ( NX + 1 )( NY + 1 ) n 1 n 1 2hx n Nx 1 n Nx 1 2hy n Nx 1 Ny 1 n Nx1 Ny 1 2hz Результаты Аксиальная инжекция пучка Процесс банчировки пучка Ускорение в циклотроне Анимация Анимация Анимация Потери частиц Ускорение банчей Оптимизация центральной области «Земля» φRF = 15° φRF = 13° Без постов F = ZURF - WGAP Дуант φRF = 28° φRF = 10° С постами Выбор оптимальной конфигурации S0 S1 S3 S2 S4 Распределение ускоряющего поля Производительность на 8800GTX CPU** GPU Ускорение, [раз] Track 486 30 16 Losses 6997 75 93 Rho 79 6 14 Poisson/FFT 35 3 13 E_SC 1.2 0.8 1.4 Total 7598 114 67 Функции* Время, [мс] *Размер сетки: 25 x 25 x 25. Число частиц: 100,000 треугольников: 2054 **CPU с частотой 2.4 ГГц Сравнение CPU и GeForce 8800GTX Число частиц Время вычислений Ускорение, [раз] CPU* GPU 1,000 3 мин. 19 c. 12 c. 17 10,000 34 мин. 14 с. 42 с. 49 100,000 5 ч. 41 мин. 6 мин. 56 1,000,000 2 дня 8 ч. 53 мин. 1 ч. 60 *CPU с частотой 2.4 ГГц Сравнение CPU с Tesla C1060 Число частиц Время вычислений Ускорение, [раз] CPU 2.5ГГц GPU C 1060 1,000 3 мин. 12 с. 11 с. 18 10,000 32 мин. 24 с. 27 с. 72 100,000 5 ч. 14 мин. 31 с. 3 мин. 34 с. 88 2 дня 4 ч. 25 мин. 34 мин. 29 с. 91 1,000,000 БЕЗ пространственного заряда Сравнение CPU с Tesla C1060 Число частиц Время вычислений Ускорение, [раз] CPU 2.5 ГГц GPU C 1060 10,000 33 мин. 36 с. 44 с. 45 100,000 5 ч. 28 мин. 12 с. 5 мин. 4 с. 65 1,000,000 2 дня 8 ч. 27 мин. 50 мин. 17 с. С пространственным зарядом 67 Эффект пространственного заряда I~0 Потери 24% I = 4 мА Потери 94% Заключение • Очень дешевая технология в сравнении с CPU; • Увеличение производительности на 1.5 – 2 порядка дает шанс проведения моделирования ресурсоемких физических моделей; • Требует аккуратного программирования.