
- •Параллельные вычисления.
- •История развития многопроцессорной вычислительной техники.
- •Классификация вычислительных систем.
- •Обзор архитектур многопроцессорных систем.
- •Одновременная многопотоковость.
- •Многоядерность.
- •Системы с массовым параллелизмом.
- •Кластерные системы.
- •Ускорители вычислений.
- •Замеры времени на видеокарте.
- •Типы памяти cuda.
- •Работа с константной памятью.
- •Работа с глобальной памятью.
- •Оптимизация работы с глобальной памятью.
- •Разделяемая память и её использование.
- •Реализация на cuda базовых операций над массивами.
- •Принципы программирования на системах с распределенной памятью.
- •Типовые схемы коммуникации в многопроцессорных вычислительных системах.
Реализация на cuda базовых операций над массивами.
Редукция, сканирование, сортировка.
Преимущества от использования cuda сильно зависят от используемых алгоритмов.
Редукция.
Пусть задан массив a0,a1,…,an-1. требуется выполнить некоторую бинарную ассоциативную операцию над ними. Редукцией данного массива относительно заданной операции будет следующая величина: A=(((a0+a1)+a2)+…+an-1).
Для редукции применим стандартный прием, при котором исходный массив делится на части, которым ставится в соответствие один блок сетки. Он будет считать сумму элементов данной части массива. Таким образом задача разбивается на набор независимых подзадач, а именно нахождение отдельных сумм массива. Далее разобьем соответствующий блок элементов массива на пары. Каждая пара параллельно складывается. В результате получается вдвое больше элементов, подлежащих суммированию. Для данной задачи главным фактором, ограничивающим быстродействие, является доступ к памяти. Поэтому удобно, чтобы каждый блок сразу скопировал элементы в разделяемую память и суммировал их уже в разделяемой памяти.
#define block_size 256
__global__ void reduce (int *inData, int *outData)
{ __shared__ int data[block_size];
int tid = threadIdx.x;
int i = blockIdx.x*blockDim.x+threadIdx.x;
data[tid] = indata[i];
__syncthreads ( );
for (int s=1; s<blockDim.x; s/=2)
{ if (tid%(2*s)==0)
data[tid]+=data[tid+s];
__syncthreads ( );
}
if (tid==0) outData[blockIdx.x]=data[0];
}
(Ui-1,j – 2*Ui,j + Ui+1,j)/h^2+( Ui,j-1 – 2*Ui,j + Ui,j+1)/h^2 = 0
Us+1i,j = ¼*( Us+1i-1,j + Usi+1,j + Us+1i,j-1+ Usi,j+1) – метод Либнана.
Есть еще метод верхней релаксации. Ui,j = Θ/4*( Ui-1,j + Ui+1,j + Ui,j-1+ Ui,j+1)+Ui,j*(1-Θ), Θ= 1,87.
Это первый этап расчета поля потенциалов.
Второй этап. I = -γ*gradU. Ix = -γ*dU/dx, Iy = -γ*dU/dy.
Ixi,j = -γi,j*(Ui+1,j-Ui-1,j)/(2*h), Iyi,j = -γi,j*(Ui,j+1-Ui,j-1)/(2*h).
Третий этап.
dT/dt = A*(d2T/dx2+d2T/dy2)+B*r*(Ix^2+Iy^2)
(Tk+1i,j – Tki,j )/t = A*((Tki-1,j – 2*Tki,j+Tki+1,j)/h^2+(Tki,j-1 – 2*Tki,j + Tki,j+1)/h^2)+B*ri,j *(Ixi,j^2+Iyi,j^2).
dNB/dt = DB*(d2NB/dx2+d2NB/dy2) – M*TBy*NB.
(Nk+1B - NkB)/r = DB*((NkBi-1,j – 2*NkBi,j+NkBi+1,j)/h^2+(NkBij-1 – 2*NkBi,j + NkBi,j+1)/h^2) – M*(Tki,j)^B*NkB.
Граничные условия.
Г1: dU/dy = 0, (Ui,ny – Ui,ny-1)/h = 0, Ui,ny = Ui,ny-1.
Г2: dU/dx = 0, (Unx,j – Unx-1,j)/h = 0, Unx,j = Unx-1,j.
Г3: Ui,1 = 0, i = nx2,…, nx.
Г4: Ui,1 = Ui,2, i=nx1+1,…,nx2-1.
Г5: Ui,1 = 40, i=1,…,nx1.
Г6: U1,j = U2,j.
Для температуры.
α*(T* - T) = λ*dT/dx, α – коэффициент теплопередачи, λ – коэффициент теплопроводности.
α*(T* - T1,j) = λ*(T1,j – T2,j)/h = Q
T1,j*(1- α*h/ λ) = T2,j + α*h/ λ*T*
T1,j = (T2,j + α*h/ λ*T*)/(1+ α*h/ λ)
Tnx,j = (Tnx-1,j + α*h/ λ*T*)/(1+ α*h/ λ)
Ti,1 = (Ti,2 + α*h/ λ*T*)/(1+ α*h/ λ)
Ti,ny = (Ti,ny-1 + α*h/ λ*T*)/(1+ α*h/ λ)
Для влажности.
α*(N* - N1,j) = λ*(N1,j – N2,j)/h
b = 878, T* = 283K, M = 75*10^(-6), B = 1,9, λ = 0,2, c = 1000, α = 4, DB = 10^(-9), ρ = 2450.
ПО, а именно качество, является сдерживающим фактором для развития параллельных систем. Основной характеристикой, определяющей стиль программирования, является наличие общей или распределенной памяти. Отличительной чертой этих систем является единая подсистема ввода-вывода, единая ОС, единая ОП. Обычно работа происходит с использованием Unix подобной ОС. Она функционирует в виде множества процессов. Каждая пользовательская программа также запускается как отдельный процесс. Механизм порождения процесса является главным принципом распараллеливания. Также его называют механизмом порождения нитей. Нить в данном контексте – это легковесный процесс, для которого не порождается отдельного адресного пространства.
В языке Си возможно прямое использование механизма порождения нитей для распараллеливания программы посредством вызова системных функций: Все производители SMP-систем включают в свое ПО распараллеливающие компиляторы. Наиболее часто поставщики SMP-систем предусматривают в компиляторах директивы для распараллеливания цикла. Довольно часто эти наборы директив не совместимы между собой, поэтому приходится распараллеливать программу отдельно для каждой платформы.
Open MP – система, являющаяся расширением и обобщением этого набора директив. Интерфейс этой системы задуман как стандарт для программирования в модели общей памяти. Он реализует идею инкрементального распараллеливания, позаимствованную из языка HPF. Согласно этой системе разработчик не создает новую параллельную программу, а добавляет в текст последовательной программы Open MP директивы. Вся программа делится на последовательные и параллельные области. Все последовательные области выполняет главная нить, порождаемая при запуске. При входе в параллельную часть главная нить порождает дополнительные нити. Наличие общей памяти не препятствует использованию технологий, разработанных для систем с распределенной памятью. Многие производители SMP предоставляют такие технологии, как MPI. В случае таких систем при использовании данной технологии в качестве коммуникационной среды выступает разделяемая память.