Нужен совет по библиотеке GPGPU

Я пишу приложение, и в итоге получается хорошо распараллеливаемая часть:

two dimensional float initialData and result arrays
for each cell (a, b) in result array:
    for each cell (i, j) in initialData:
        result(a, b) += someComputation(initialData(i, j), a, b, i, j, some global data...);

Еще немного об алгоритме:

  • Я хотел бы, чтобы итерации первого цикла выполнялись одновременно (возможно, есть лучший подход?)
  • Исходные данные доступны только для чтения
  • someComputation довольно прост, он включает в себя умножение, сложение, вычисление косинуса, поэтому его можно выполнить с помощью графического процессора, однако ему нужны индексы элементов, над которыми он работает в данный момент.
  • Массивы не превышают ~ 4000 в любом измерении.

Свойства библиотеки:

  • Программа будет написана на C# (с WPF), поэтому было бы неплохо, если бы она (уже) имела простые в использовании привязки .NET.
  • Если графический процессор не найден, алгоритм должен выполняться на процессоре.
  • Программа будет только для Windows, и поддержка Windows XP крайне предпочтительна.
  • Алгоритм можно переписать на OpenCL, однако я считаю, что он не так широко поддерживается, как пиксельные шейдеры. Но, если нет альтернатив, OpenCL вполне подойдет. (AFAIK CUDA работает только на графических процессорах nVidia, а OpenCL распространяется как на графические процессоры nVidia, так и на графические процессоры AMD)

Я попытался посмотреть библиотеку Microsoft Accelerator, но не нашел способа передать индексы массива. Любая помощь будет оценена и извините меня за мой английский.


person Community    schedule 12.01.2012    source источник
comment
однако я считаю, что он не так широко поддерживается, как пиксельные шейдеры - ну, это зависит от: если вы хотите поддерживать старое оборудование (до DirectX10, это правда), однако вы можете запускать OpenCL на процессоре, поэтому напишите свой код для отката к процессору довольно прост (конечно, использование одного и того же пути кода, вероятно, будет неоптимальным, но все же (кроме того, что наиболее критический путь, вероятно, в любом случае требует разных реализаций для AMD и NVIDIA (возможно, разных поколений)).   -  person Grizzly    schedule 12.01.2012
comment
Как только вы это заработаете, не забывайте, что процессоры и графические процессоры разные. Процессоры нуждаются в более детализированной многопоточности, потому что у них мало аппаратных потоков, а графические процессоры хотят более мелкозернистой многопоточности, потому что у них много аппаратных потоков. Это означает, что вы можете настроить свои циклы FOR в зависимости от того, какая арка.   -  person Bengie    schedule 12.01.2012
comment
@Grizzly, я хотел бы поддерживать как можно более широкий спектр оборудования (конечно, с меньшим количеством кода или с простым способом определить, на каком аппаратном обеспечении работает программа, чтобы выбрать вариант алгоритма).   -  person    schedule 12.01.2012
comment
@Bengie, этот алгоритм нельзя оптимизировать, поэтому при запуске на ЦП он просто ухудшится (поскольку итерации будут выполняться последовательно), тогда как на графическом процессоре он будет работать быстрее (поскольку могут быть некоторые параллельные итерации).   -  person    schedule 12.01.2012
comment
@EdgeLuxe: я не знаю, как именно выглядят ваши вычисления, но я бы посоветовал держаться подальше от gpgpu на оборудовании до DX10, поскольку это редко стоит хлопот (для хорошей производительности вы можете в конечном итоге написать путь кода для каждого поколения DX9 и по-прежнему получают только очень умеренное ускорение). Суть настройки заключалась в том, что вы не можете запустить один и тот же код на разных аппаратных платформах и сделать его оптимальным для всех из них. Он может работать на всех из них, но для некоторых производительность может быть довольно плохой.   -  person Grizzly    schedule 12.01.2012
comment
@Grizzly, думаю, вы правы - было бы нормально оставить версию процессора для более старого оборудования. Ну, может быть, даже если код не оптимален для какого-то железа, в этом случае он все равно будет работать меньше или ок. в то же время, как если бы он был запущен на процессоре, не так ли?   -  person    schedule 12.01.2012
comment
@EdgeLuxe: не обязательно, писать эффективный код для старых GPU непросто. Для графического процессора неоптимальность может легко означать порядки. Даже для современных графических процессоров вы легко можете получить, что ваш код будет работать не быстрее на графическом процессоре, чем на процессоре, если вы допустите небольшие ошибки (ошибка с учетом производительности, а не правильности). Эти ошибки различны для разных поколений оборудования, но более старое оборудование обычно имеет больше ограничений (и медленнее по сравнению с процессором), поэтому оно может легко стать на порядок медленнее, чем процессор для оборудования класса dx9.   -  person Grizzly    schedule 12.01.2012
comment
Запуск кода, оптимизированного для графического процессора, на ЦП, как правило, не так уж и плох, но вам часто приходится выполнять избыточные операции на графическом процессоре (инициализация и т. д.) и часто приходится использовать менее оптимальные алгоритмы для обеспечения массивного распараллеливания, поэтому он все равно может быть намного медленнее. затем кодовый путь для конкретного процессора   -  person Grizzly    schedule 12.01.2012
comment
Я сделал небольшой тест, и оказалось, что версия OpenCL работает быстрее на моей 8600GTS, чем на процессоре. Надеюсь, я смогу написать один и тот же код, который подходит как для процессора, так и для графического процессора.   -  person    schedule 12.01.2012
comment
Для простоты использования из C # эти два выглядят многообещающими (для меня ;-) - Cudafy и Tidepowrd GPU.NET   -  person IvoTops    schedule 14.08.2012


Ответы (1)


Существуют низкоуровневые привязки OpenCL: OpenCL.NET: http://openclnet.codeplex.com/. Также существуют привязки на основе OpenCL.NET для F#: https://github.com/YaccConstructor/Brahma.FSharp

Он позволяет вам писать «родной» код F# и запускать его на графическом процессоре через OpenCL. Например, код для умножения матриц (без настройки провайдера):

//Code for run on GPU
let command = 
    <@
        fun (r:_2D) columns (a:array<_>) (b:array<_>) (c:array<_>) -> 
            let tx = r.GlobalID0
            let ty = r.GlobalID1
            let mutable buf = c.[ty * columns + tx]
            for k in 0 .. columns - 1 do
                buf <- buf + (a.[ty * columns + k] * b.[k * columns + tx])
            c.[ty * columns + tx] <- buf
    @>

//compile code and configure kernel
let kernel, kernelPrepare, kernelRun = provider.Compile command
let d =(new _2D(rows, columns, localWorkSize, localWorkSize))
kernelPrepare d columns aValues bValues cParallel
//run computations on GPU
let _ = commandQueue.Add(kernelRun()).Finish()            

//read result back
let _ = commandQueue.Add(cParallel.ToHost(kernel)).Finish()
person gsv    schedule 25.01.2013