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兼容。请让我知道我的错误。
完整详情: https://drive.google.com/file/d/0B16PrXUjs69zRjFhSHhOSTI5RzQ/view?usp=sharing
答案 0 :(得分:2)
这不是关于如何解决它的完整答案,而是更多解释为什么GPU不会加速,但实际上会极大地降低代码速度。
GPU非常适合加速并行代码,这意味着它们可以同时执行大量操作(即我的GPU可以同时执行30070个操作,而现代CPU不能超过16个)。但是,GPU处理器非常慢!如今一款体面的CPU拥有大约2~3GHz的速度,而现代GPU拥有700Mhz。这意味着CPU比GPU快得多,但是因为GPU可以同时做很多事情,所以它们可以赢得整体。
有一次我看到它解释为:你喜欢什么,百万美元的跑车还是踏板车?一百万dolar汽车还是一千辆踏板车?如果你的工作是送披萨怎么办?希望你为最后一个回答了一千辆踏板车(除非你是一个踏板车爱好者并且你回答了所有踏板车,但这不是重点)。 (source and good introduction to GPU)
回到你的代码:你的代码是令人难以置信的顺序。每个内部迭代都依赖于前一个迭代,并且与外部迭代相同。您无法并行运行其中的两个,因为您需要一次迭代的结果才能运行下一个迭代。这意味着在你交付最后一个之前你不会得到披萨订单,因此你想要的是尽可能快地提供1比1(所以跑车更好!)。
实际上,这些1线方程中的每一个都非常快!如果我在我的计算机上运行50个,我在该行上获得13.034秒,每次迭代为1.69 微秒(7680000次调用)。
因此,您的问题并不是您的代码很慢,而是您称之为很多次。 GPU不会加速这行代码,因为它已经非常快,而且我们知道CPU比这些东西更快。
因此,不幸的是,GPU很难用于顺序代码而且你的代码非常顺序,因此你不能使用GPU加速。 HPC既不会有帮助,因为每个循环迭代都取决于前一个循环(没有parfor
:()。
所以,我可以说,你需要处理它。