Общий обзор параллельной обработки см. По ссылке Андреса в его комментарии.
Вот мой взгляд на распараллеливание GPU:
Представьте себе простой сценарий, в котором вы хотите подкрасить каждый пиксель на экране синим цветом. Если вы делали все это на процессоре в одном потоке на гипотетическом 1024x1024 пиксельном дисплее, вы могли бы написать что-то вроде этого
/// increase the blue component of an individual pixel
RGB32 TintPixelBlue(RGB32 inputPixel)
{
/// increase the blue component by a max of 10, but don't overflow the byte by going over
/// 0xFF
inputPixel.Blue += Math.Min(10,0xFF-inputPixel.Blue)
return inputPixel;
}
void DrawImageToScreen(Image image)
{
for(int y=0;y<pixels.Height;y++)
for(int x=0;x<pixels.Width;x++)
image[x,y]=TintPixelBlue(image[x,y]);
DrawMyImageToScreen(image);
}
Для изображения 1024x1024 это должно будет выполняться 1 048 576 раз, один пиксель за другим. Это может занять довольно много времени. Если вам нужно сделать это, скажем, со скоростью 60 кадров в секунду и нарисовать кучу других вещей (вашу сцену или другую геометрию), ваша машина может затормозить. Это становится еще хуже, если вы работаете с большим изображением (например, 1920x1080).
Введите распараллеливание. (ДЕЙСТВИТЕЛЬНО грубый псевдокод; см. HLSL , CUDA или OpenCL для реальной вещи)
RGB32 TintPixelBlue(RGB32 inputPixel)
{
/// increase the blue component by a max of 10, but don't overflow the byte by going over
/// 0xFF
inputPixel.Blue += Math.Min(10,0xFF-inputPixel.Blue)
return inputPixel;
}
void DrawImageToScreen(Image image)
{
GPU.SetImage(image);
GPU.SetPixelShader(TintPixelBlue);
Draw();
}
Используя один многоядерный графический процессор (до 512 ядер на картах NVidia Fermi и Tesla), вы можете написать функцию TintPixelBlue()
на шейдерном языке, который компилируется в собственный набор команд графического процессора. Затем вы передаете объект Image в графический процессор и приказывает ему запускать TintPixelBlue()
на каждом пикселе. Затем графический процессор может использовать все 512 ядер параллельно, что эффективно делит требуемое время на количество ядер (минус накладные расходы и некоторые другие вещи, которые мы не будем здесь рассматривать).
Вместо 2 ^ 20 = 1 048 576 итераций на ЦП вы получите 1 048 576/512 или 2 ^ 11 = 2048 итераций. Это (очевидно) увеличение производительности примерно в 500 раз.
Ключевым моментом здесь является то, что каждый вход является независимым: вам не нужно, чтобы выход одного пикселя влиял на другой, поэтому любое свободное ядро может работать с любым ожидающим входом без необходимости синхронизации с другими ядрами.
Настоящее веселье начинается, когда вы устанавливаете несколько графических процессоров в систему. Массивы Tesla невероятно быстрые и обеспечивают работу самого быстрого в мире суперкомпьютера . Учитывая, что они значительно дешевле, чем массив традиционных процессоров Equivelant (сравните стоимость 512 1,3 ГГц процессоров, оперативной памяти, места в стойке и т. Д. С картой Tesla за 3000 долларов США), они становятся очень популярными в научном сообществе для жестких хруст номера.
Надеюсь, это поможет.