2015-11-10 2 views
2
function w=oja(X, varargin) 

% get the dimensionality 
[m n] = size(X); 

% random initial weights 
w = randn(m,1); 

options = struct(... 
    'rate', .00005, ... 
    'niter', 5000, ... 
    'delta', .0001); 
options = getopt(options, varargin); 
success = 0; 

% run through all input samples 
for iter = 1:options.niter 
    y = w'*X; 
    for ii = 1:n  
     % y is a scalar, not a vector 
     w = w + options.rate*(y(ii)*X(:,ii) - y(ii)^2*w); 
    end 
end 
if (any(~isfinite(w))) 
    warning('Lost convergence; lower learning rate?'); 
end 

end 

size(X)= 400 153600 

Этот код реализует правило oja и работает медленно. Я не могу его векторизовать. Для того, чтобы сделать его работать быстрее, я хотел бы сделать вычисления на GPU, поэтому я изменилОптимизация графического процессора для векторизованного кода

X=gpuArray(X) 

Но код вместо бежал медленнее. Используемое вычисление, похоже, совместимо с GPU. Пожалуйста, дайте мне знать мою ошибку.

Профиль код Выход: enter image description here

Полная информация: https://drive.google.com/file/d/0B16PrXUjs69zRjFhSHhOSTI5RzQ/view?usp=sharing

+0

Помните * Ранняя оптимизация корень всего зла *. Можете ли вы рассказать о своем коде? Какая часть является самой медленной частью? Можете ли вы опубликовать результат профилирования MATLABs? –

+0

@AnderBiguri Привет, Спасибо за ответ! Пожалуйста, проверьте текущий выходной код профиля. Вопрос: –

+0

You Правильно. Избегайте использования GPU здесь, это делает его невероятно медленным **, и у меня есть TESLA k40. –

ответ

2

Это не полный ответ о том, как решить эту проблему, но скорее объяснение, почему графические процессоры не ускорить, но на самом деле чрезвычайно медленно вниз по вашему коду.

Графические процессоры являются фантастическими для ускорения параллельного кода, что означает, что они могут делать много вещей одновременно (т. Е. Мой GPU может одновременно делать 30070 штук, в то время как современный процессор не может переходить через 16) , Однако графические процессоры очень медленные! В настоящее время приличный процессор имеет скорость около 2 ~ 3Ghz, а современный GPU - 700 МГц. Это означает, что процессор намного быстрее, чем GPU, но поскольку графические процессоры могут делать много вещей, в то же время они могут выиграть в целом.

Как только я увидел, что это объясняется как: Что вы предпочитаете, спортивный автомобиль или скутер на миллион долларов? Миллион дольских автомобилей или тысячи скутеров? А что, если ваша задача - доставить пиццу? Надеюсь, вы ответили на тысячу скутеров за эту последнюю (если вы не поклонник скутера, и вы ответили на скутеры во всех из них, но это не главное). (source and good introduction to GPU)

Обратно к вашему коду: ваш код невероятно последователен. Каждая внутренняя итерация зависит от предыдущей и той же самой с внешней итерацией. Вы не можете запустить 2 из них параллельно, так как вам нужен результат от одной итерации, чтобы запустить следующую. Это означает, что вы не получите заказ на пиццу до тех пор, пока не получите последний, так что вы хотите доставить 1 к 1, как можно быстрее (так что спортивный автомобиль лучше!).

И на самом деле, каждое из этих 1 линейных уравнений невероятно быстро! Если я запустил 50 из них на своем компьютере, я получаю 13.034 секунды на этой строке, которая составляет 1,69 микросекунд за итерацию (7680000 звонков).

Таким образом, ваша проблема не в том, что ваш код работает медленно, это вы называете его A LOT раз. Графический процессор не будет ускорять эту строку кода, потому что это уже очень быстро, и мы знаем, что процессоры быстрее, чем GPU для такого рода вещей.

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

Итак, насколько я могу сказать, что вам нужно будет иметь дело с ним.

+0

Спасибо за подробный ответ. Интересно, почему-то это можно было бы векторизовать больше, чтобы уменьшить количество вызовов. Зависимость между итерациями ограничивает меня. –

+0

@AbhishekBhatia, как вы говорите, зависимость ограничивает вас. Я пытался думать о векторизованном коде, но на самом деле уравнение вычисляется уже с очень высокой скоростью. Я честно не думаю, что есть способ ускорить это. –

+0

Да, вы правы. Вместо этого я хотел уменьшить вызовы функций. Возможно, они могут ускорить это. –