GPU код выполняется дольше, чем обычный

Обсуждение вопросов связанных с параллельными и распределенными вычислениями

Модератор: Admin

alexandr1991
Пользователь
Сообщения: 47
Зарегистрирован: Ср окт 10, 2012 12:10 am

GPU код выполняется дольше, чем обычный

Сообщение alexandr1991 » Ср дек 25, 2013 10:12 pm

Здравствуйте! Вот проблема
clear all

% g = gpuDevice(1);
% reset(g);
X = rand(1,10^6 );
tic;
G = gpuArray( X );
s=fft(G);
S=gather(s);

toc


X = rand(1,10^6 );
tic;
s=fft(X);
toc

Elapsed time is 130.082063 seconds.
Elapsed time is 0.042482 seconds.

Как такое может быть? Иногда, кстати, GPU код выполняется, как и положено, быстрее.
С уважением, Вознесенский Александр

Сергей aka Грифон
Пользователь
Сообщения: 857
Зарегистрирован: Вс ноя 22, 2009 4:24 pm

Re: GPU код выполняется дольше, чем обычный

Сообщение Сергей aka Грифон » Чт дек 26, 2013 12:03 am

1. У Вас в соседнем окне Crysis/Rome Total War или ещё что-то не развёрнуто? может, конкуренция задач, и матлаб проигрывает?
2. По личному опыту рекомендую использовать для расчётов и подключения монитора разные видюхи, благо сейчас вполне пристойную подержанную неигровую видюху можно купить за те же деньги, что и блок сигарет, а интегрированное видео тоже стало очень неплохим.
При наличии доступа к гуглу студент обязан быть богоподобен

alexandr1991
Пользователь
Сообщения: 47
Зарегистрирован: Ср окт 10, 2012 12:10 am

Re: GPU код выполняется дольше, чем обычный

Сообщение alexandr1991 » Чт дек 26, 2013 12:33 am

Нет, запущен только матлаб. Вообще сколько времени занимает запись данных в память GPU и возврат их в матлаб? Я понимаю, что это зависит от объема данных, но все таки, каковы накладные расходы по сравнению с выигрышем по вычислениям?
С уважением, Вознесенский Александр

Harmont
Пользователь
Сообщения: 43
Зарегистрирован: Пт дек 04, 2009 1:11 pm

Re: GPU код выполняется дольше, чем обычный

Сообщение Harmont » Пн янв 12, 2015 1:03 pm

У меня на Quadro 4000 Ваш код выполняется где то за 0,017 секунд. Запускал код раз 15 - 20.

Harmont
Пользователь
Сообщения: 43
Зарегистрирован: Пт дек 04, 2009 1:11 pm

Re: GPU код выполняется дольше, чем обычный

Сообщение Harmont » Пн янв 12, 2015 1:10 pm

Запустите вот такой скрипт:
g = gpuDevice(1);
X = rand(1,10^6 );
tic;
G = gpuArray( X );
s=fft(G);
wait(g)
toc
Выигрыш по времени где то в 1,7 раза. По возможности нужно избегать передачу промежуточных данных из GPU в CPU, а передавать только конечные данные.

sandy
Эксперт
Сообщения: 5525
Зарегистрирован: Ср сен 22, 2004 4:49 pm

Re: GPU код выполняется дольше, чем обычный

Сообщение sandy » Пн янв 12, 2015 3:38 pm

Замените 10^6 на степень двойки (в качестве близкого значения подойдет 2^20), и вариант с GPU станет быстрее (у меня, по крайней мере, стал). Похоже, процедура вычисления FFT для GPU менее вылизана для работы с произвольными длинами массивов, чем используемая ядром матлаба библиотека FFTW.

P.S. Правда, и на вашем исходном коде результата в 130 секунд у меня не наблюдалось. Разница между двумя вариантами была очень маленькая.
С уважением

Александр Сергиенко

Harmont
Пользователь
Сообщения: 43
Зарегистрирован: Пт дек 04, 2009 1:11 pm

Re: GPU код выполняется дольше, чем обычный

Сообщение Harmont » Пн янв 12, 2015 5:47 pm

Еще при проблемах и "необычном" поведении GPU желательно выгружать ядро GPU командой - gpuDevice([])

Skazzi
Пользователь
Сообщения: 68
Зарегистрирован: Вт июл 14, 2009 2:41 pm

Re: GPU код выполняется дольше, чем обычный

Сообщение Skazzi » Ср апр 15, 2015 8:15 am

А у меня такая история: если изображение большое, то свертка на видеокарте быстрее, но если изображение маленькое – дольше.

Код: Выделить всё

A=imread('saturn.png');
A=imresize(A,0.125);
A=rgb2gray(A);
A=im2double(A);
Z=[0,0,0,0,0,0,1,1;0,0,0,0,1,1,0,0;0,0,0,1,0,0,0,0;0,0,1,0,0,0,0,0;0,1,0,0,0,0,0,0;0,1,0,0,0,0,0,0;1,0,0,0,0,0,0,0;1,0,0,0,0,0,0,0;];

tic
y2=conv2(A,Z,'full');
toc

gpuDevice([])
A1=gpuArray(A);
Z1=gpuArray(Z);

tic
y1=conv2(A1,Z1,'full');
toc


Elapsed time is 0.000340 seconds.
Elapsed time is 0.001256 seconds.

Как это можно объяснить?

sandy
Эксперт
Сообщения: 5525
Зарегистрирован: Ср сен 22, 2004 4:49 pm

Re: GPU код выполняется дольше, чем обычный

Сообщение sandy » Ср апр 15, 2015 9:32 am

Собственно, так и должно быть - вы на обмен данными с GPU тратите больше времени, чем на сам расчет.
С уважением



Александр Сергиенко

Skazzi
Пользователь
Сообщения: 68
Зарегистрирован: Вт июл 14, 2009 2:41 pm

Re: GPU код выполняется дольше, чем обычный

Сообщение Skazzi » Ср апр 15, 2015 12:15 pm

хм, я думала если таймер включается уже после создания массивов для GPU , то он покажет непосредственно время вычисления. Любопытно, что данный код после перезагрузки компа на GPU показал меньшее время вычислений на 3 порядка. Но при повторных запусках цифры вернулись к написанным выше значениям.

И если можно один вопрос про распараллеливание. Есть большое изображение. И с каждым пикселем надо произвести определенную операцию. В цикле, естественно, очень долго. Каким образом это будет проще и понятнее сделать в параллельном варианте? Куда смотреть, parallel toolbox, CUDA? (с С++ не особо, ява ближе, но хотелось бы вообще не выходить далеко за пределы матлаба).

sandy
Эксперт
Сообщения: 5525
Зарегистрирован: Ср сен 22, 2004 4:49 pm

Re: GPU код выполняется дольше, чем обычный

Сообщение sandy » Ср апр 15, 2015 4:06 pm

Не посмотрел, где именно в коде стоял таймер. Тогда немного уточню свой ответ: при малом объеме вычислений вы больше теряете из-за затрат на диспетчеризацию распараллеливания, чем выигрываете благодаря собственно распараллеливанию. Про изменение времени после перезагрузки ничего предположить не могу.

Насчет операций с каждым пикселом - а что сделать-то нужно? Возможности оптимизации сильно зависят от выполняемых операций.
С уважением



Александр Сергиенко

Skazzi
Пользователь
Сообщения: 68
Зарегистрирован: Вт июл 14, 2009 2:41 pm

Re: GPU код выполняется дольше, чем обычный

Сообщение Skazzi » Ср апр 15, 2015 5:44 pm

Понятно. Как ни странно, ситуация с перезагрузкой повторилась снова, видимо там "своя жизнь" :roll: .
К каждому пикселю добавляется какое-то число (случайное) и после этого считается функция ошибки с учетом этого изменения (деконволюция, J(f,h)=(f*h-g)^2). И так по всему изображению. По сути все это можно сделать одновременно, т.к. все операции независимые друг от друга. Что для этого подойдет?

sandy
Эксперт
Сообщения: 5525
Зарегистрирован: Ср сен 22, 2004 4:49 pm

Re: GPU код выполняется дольше, чем обычный

Сообщение sandy » Пт апр 17, 2015 12:02 am

По сути все это можно сделать одновременно, т.к. все операции независимые друг от друга.

Необходимые действия выражаются стандартными матричными операциями или нет? Если да, то я не вполне понимаю вопрос - в ядре уже все неплохо распараллелено и есть реализация стандартных операций на GPU.
С уважением



Александр Сергиенко

Skazzi
Пользователь
Сообщения: 68
Зарегистрирован: Вт июл 14, 2009 2:41 pm

Re: GPU код выполняется дольше, чем обычный

Сообщение Skazzi » Пт апр 17, 2015 7:36 am

Вопросы от неопытности. Вроде, ничего необычного в коде нет
например, f0 - изображение (матрица M на N).
Нужно сделать

Код: Выделить всё

for i=1:iter_num
       f=f0;
      f(1,1)=f(1,1)+a1
      J=(conv2(f,h)-g)^2
проверка условия, увеличилась или уменьшилась J
      f=f0;
      f(2,1)=f(2,1)+a2
      J=(conv2(f,h)-g)^2
проверка условия, увеличилась или уменьшилась J
 и т.д. по всем пикселям.
end


Мне не понятно, на каком этапе переходить на GPU? Сразу грузить изображение в gpuArray и все там считать? Как там сделать прогон по всем пикселям? Два вложенных цикла for или что-то другое есть?

sandy
Эксперт
Сообщения: 5525
Зарегистрирован: Ср сен 22, 2004 4:49 pm

Re: GPU код выполняется дольше, чем обычный

Сообщение sandy » Пт апр 17, 2015 11:27 am

Код: Выделить всё

J=(conv2(f,h)-g)^2

Что на самом деле имелось в виду? Вычислить эту строку удастся только если g - квадратная матрица, но результат тоже будет матрицей! Может быть, имелась в виду сумма квадратов разностей по всей матрице?

И еще: откуда берутся a1, a2 и т. д.? Практический смысл этого кода неясен.

Если я правильно догадываюсь, что на самом деле имеется в виду, это можно сделать с помощью blockproc, так как ваш расчет на самом деле затрагивает не всю матрицу, а только некоторую окрестность точки, определяемую размером матрицы h.
С уважением



Александр Сергиенко