我想在一台机器上(而不是集群)并行化Octave中的for循环。我刚才问了一个关于Octave的并行版本的问题 parallel computing in octave
答案表明我下载了一个并行计算软件包,我做了。该软件包似乎主要面向集群计算,但确实提到了单机并行计算,但对如何运行并行循环并不清楚。
我还发现了另外一个关于此问题的问题,但我找不到在Octave中并行化循环的好答案: Running portions of a loop in parallel with Octave?
有谁知道我在哪里可以找到在Octave中并行运行for循环的例子
答案 0 :(得分:12)
我正在计算大量的RGB直方图。我需要使用显式循环来完成它。因此,每个直方图的计算花费了显着的时间。因此,并行运行计算是有意义的。在Octave中,有一个由Jaroslav Hajek编写的(实验性)函数parcellfun可以用来做它。
我原来的循环
histograms = zeros(size(files,2), bins^3);
% calculate histogram for each image
for c = 1 : size(files,2)
I = imread(fullfile(dir, files{c}));
h = myhistRGB(I, bins);
histograms(c, :) = h(:); % change to 1D vector
end
要使用parcellfun,我需要将循环体重构为一个单独的函数。
function histogram = loadhistogramp(file)
I = imread(fullfile('.', file));
h = myhistRGB(I, 8);
histogram = h(:); % change to 1D vector
end
然后我可以这样称呼它
histograms = parcellfun(8, @loadhistogramp, files);
我在计算机上做了一个小基准测试。它是4个物理内核,启用了Intel HyperThreading。
我的原始代码
tic(); histograms2 = loadhistograms('images.txt', 8); toc();
warning: your version of GraphicsMagick limits images to 8 bits per pixel
Elapsed time is 107.515 seconds.
使用parcellfun
octave:1> pkg load general; tic(); histograms = loadhistogramsp('images.txt', 8); toc();
parcellfun: 0/178 jobs donewarning: your version of GraphicsMagick limits images to 8 bits per pixel
warning: your version of GraphicsMagick limits images to 8 bits per pixel
warning: your version of GraphicsMagick limits images to 8 bits per pixel
warning: your version of GraphicsMagick limits images to 8 bits per pixel
warning: your version of GraphicsMagick limits images to 8 bits per pixel
warning: your version of GraphicsMagick limits images to 8 bits per pixel
warning: your version of GraphicsMagick limits images to 8 bits per pixel
warning: your version of GraphicsMagick limits images to 8 bits per pixel
parcellfun: 178/178 jobs done
Elapsed time is 29.02 seconds.
(并行和串行版本的结果相同(仅转置)。
octave:6> sum(sum((histograms'.-histograms2).^2))
ans = 0
当我多次重复这个时,运行时间几乎都是一样的。并行版本运行大约30秒(+ - 约2s),包括4个,8个和16个子过程)
答案 1 :(得分:10)
Octave循环缓慢,缓慢,缓慢,你在表达数组操作方面做得更好。让我们举一个例子来评估2d域上的一个简单的trig函数,就像在这个3d octave graphics example中一样(但是计算的点数更加真实,而不是绘图):
vectorized.m:
tic()
x = -2:0.01:2;
y = -2:0.01:2;
[xx,yy] = meshgrid(x,y);
z = sin(xx.^2-yy.^2);
toc()
将它转换为for循环给了我们 forloops.m:
tic()
x = -2:0.01:2;
y = -2:0.01:2;
z = zeros(401,401);
for i=1:401
for j=1:401
lx = x(i);
ly = y(j);
z(i,j) = sin(lx^2 - ly^2);
endfor
endfor
toc()
请注意,矢量化版本已经“赢得”更简单,更清晰,但也有另一个重要优势;时间截然不同:
$ octave --quiet vectorized.m
Elapsed time is 0.02057 seconds.
$ octave --quiet forloops.m
Elapsed time is 2.45772 seconds.
因此,如果您使用for循环,并且您具有完美的并行性而没有开销,那么您必须将其分解为119个处理器,以便在非循环中实现收支平衡!
不要误会我的意思,并行性很好,但首先要让事情有效地串联起来。
几乎所有八度音程的内置函数都已经过矢量化,因为它们在标量或整个数组上运行得相同;因此,将事物转换为数组操作通常很容易,而不是逐个元素地执行操作。对于那些不那么容易的时候,你通常会看到有一些实用函数(比如meshgrid,它从2个向量的笛卡尔积中生成一个二维网格)已经存在以帮助你。
答案 2 :(得分:4)
现在可以在那里找到pararrayfun
用法示例:
http://wiki.octave.org/Parallel_package