Matlab, если заявления с CUDA - PullRequest
3 голосов
/ 29 января 2012

У меня есть следующий код Matlab:

randarray = gpuArray(rand(N,1));
N = 1000;

tic
g=0;
for i=1:N

    if randarray(i)>10
        g=g+1;
    end

end
toc

secondrandarray = rand(N,1);
 g=0;

 tic 
for i=1:N

    if secondrandarray(i)>10
        g=g+1;
    end

end
toc



Elapsed time is 0.221710 seconds.
Elapsed time is 0.000012 seconds.

1) Почему предложение if на GPU так медленно? Это замедляет все мои попытки оптимизации

2) Что я могу сделать, чтобы обойти это ограничение?

Спасибо

Ответы [ 4 ]

6 голосов
/ 29 января 2012

Как правило, это плохая вещь, независимо от того, выполняете ли вы ее на процессоре или процессоре.

Следующее будет хорошим способом выполнения операции, которую вы просматриваете.

N = 1000;
randarray = gpuArray(100 * rand(N,1));
tic
g = nnz(randarray > 10);
toc

У меня нет PCT, и я не могу проверить, действительно ли это работает (количество функций, поддерживаемых на GPU, довольно ограничено).

Однако, если у вас было Jacket ,Вы определенно сможете сделать следующее.

N = 1000;
randarray = gdouble(100 * rand(N, 1));
tic
g = nnz(randarray > 10);
toc

Полное раскрытие: я один из инженеров, разрабатывающих Jacket.

1 голос
/ 30 января 2012

Используя MATLAB R2011b и Parallel Computing Toolbox на довольно старом сейчас GPU (Tesla C1060), вот что я вижу:

>> g = 100*parallel.gpu.GPUArray.rand(1, 1000);
>> tic, sum(g>10); toc
Elapsed time is 0.000474 seconds.

Работа со скалярными элементами одного gpuArray по одному всегда будет медленной, поэтому использование метода sum намного быстрее.

1 голос
/ 29 января 2012

Нет эксперта по реализации Matlab gpuArray, но я подозреваю, что каждый randarray(i) доступ в первом цикле инициирует транзакцию PCI-e для извлечения значения из памяти GPU, что повлечет за собой очень большой штраф за задержку. Возможно, вам лучше будет позвонить gather, чтобы вместо этого передать весь массив в одной транзакции, а затем перебрать локальную копию в памяти хоста.

0 голосов
/ 27 сентября 2012

Я не могу комментировать предыдущее решение, потому что я слишком нов, но продолжаю решение от Павана.Функция nnz (еще не реализована) для gpuArrays, по крайней мере, в версии Matlab, которую я использую (R2012a).

В общем, гораздо лучше векторизовать код Matlab.Однако в некоторых случаях зацикленный код может работать быстро в Matlab из-за компиляции JIT.

Проверьте результаты из

N = 1000;
randarray_cpu = rand(N,1);
randarray_gpu = gpuArray(randarray_cpu);
threshold     = 0.5;

% CPU: looped
g=0;
tic
for i=1:N
    if randarray_cpu(i)>threshold
        g=g+1;
    end
end
toc

% CPU: vectorized
tic
g = nnz(randarray_cpu>threshold);
toc

% GPU: looped
tic
g=0;
for i=1:N
    if randarray_gpu(i)>threshold
        g=g+1;
    end
end
toc

% GPU: vectorized
tic
g_d = sum(randarray_gpu > threshold);
g = gather(g_d); % I'm assuming that you want this in the CPU at some point
toc

Что (на моем ядре i7 + GeForce 560Ti):

Elapsed time is 0.000014 seconds.
Elapsed time is 0.000580 seconds.
Elapsed time is 0.310218 seconds.
Elapsed time is 0.000558 seconds.

Итак, что мы видим из этого случая:

Циклы в Matlab не считаются хорошей практикой, но в вашем конкретном случае они работают быстро, потому что Matlab каким-то образом «прекомпилирует» его внутренне.Я изменил ваш порог с 10 до 0,5, так как rand никогда не даст вам значение, превышающее 1.

Зацикленная версия GPU работает ужасно, потому что на каждой итерации цикла запускается ядро ​​(или данные считываются изGPU, однако TMW реализовал это ...), что медленно.Множество небольших переносов памяти при вычислении практически ничего не худшее, что можно сделать на графическом процессоре.

Исходя из последнего (лучшего) результата графического процессора, ответ будет таким: если данные уже находятся на графическом процессоре,не имеет смысла вычислять это на GPU.Поскольку арифметическая сложность вашей операции в основном отсутствует, накладные расходы на передачу памяти никоим образом не окупаются.Если это часть больших вычислений на GPU, это нормально.Если нет ... лучше придерживаться процессора;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...