Documentation from Matlab:
bsxfun:
Apply element-by-element binary operation to two arrays withsingleton expansion enabled.
repmat:
Replicate and tile an array.
Overview:
There are two approaches to apply element-by-element binary operation to two arrays with singleton expansion enabled, using bsxfun directly or applying repmat first and then make binary operation .
Example:
>> a=rand(3,2)
a =
0.8721 0.3843
0.9016 0.0373
0.9518 0.9271
>> b=zeros(3,1)
b =
0
0
0
>> bsxfun(@minus,a,b) % operation with singleton expansion enabled
ans =
0.8721 0.3843
0.9016 0.0373
0.9518 0.9271
>> a-b % operation with singleton expansion disabled
Error using -
Matrix dimensions must agree.
>> a-repmat(b,1,2)
ans =
0.8721 0.3843
0.9016 0.0373
0.9518 0.9271
Speed test:
As shown in the graph, bsxfun is almost twice faster than repeat.
Why bsxfun is faster:
There are two reasons why bsxfun is faster than the other approach:
1. bsxfun avoids explicit allocation of memory and actual replication of the array;
2. bsxfun is one of the multi-threaded Matlab functions.
Furthermore...
Is it a good idea to replace normal (vars in same dimension) element-by-element operation with bsxfun?
As shown in the graph, there is no need to replace normal element-by-element operation with bsxfun.
Appendix 1.
Comparison of bsxfun and repmat.
clear;
n = 300;
k = 1;
a = ones(10,1);
repmat_result = zeros(n,1);
bsxf_result = zeros(n,1);
num_repeat = 100;
tt = zeros(num_repeat,1);
for i = 1:n;
r = rand(1,i*k);
for it = 1:num_repeat;
tic,
x = bsxfun(@plus,a,r);
tt(it) = toc;
end;
bsxf_result(i) = mean(tt) / n;
for it = 1:num_repeat;
tic,
y = repmat(a,1,i*k)+repmat(r,10,1);
tt(it) = toc;
end;
repmat_result(i) = mean(tt) / n;
plot(bsxf_result,'-r')
hold on
plot(repmat_result,'-b')
bsxfun:
Apply element-by-element binary operation to two arrays withsingleton expansion enabled.
repmat:
Replicate and tile an array.
Overview:
There are two approaches to apply element-by-element binary operation to two arrays with singleton expansion enabled, using bsxfun directly or applying repmat first and then make binary operation .
Example:
>> a=rand(3,2)
a =
0.8721 0.3843
0.9016 0.0373
0.9518 0.9271
>> b=zeros(3,1)
b =
0
0
0
>> bsxfun(@minus,a,b) % operation with singleton expansion enabled
ans =
0.8721 0.3843
0.9016 0.0373
0.9518 0.9271
>> a-b % operation with singleton expansion disabled
Error using -
Matrix dimensions must agree.
>> a-repmat(b,1,2)
ans =
0.8721 0.3843
0.9016 0.0373
0.9518 0.9271
Speed test:
Below is a speed test of the two approaches. Please find code at Appendix 1.
Why bsxfun is faster:
There are two reasons why bsxfun is faster than the other approach:
1. bsxfun avoids explicit allocation of memory and actual replication of the array;
2. bsxfun is one of the multi-threaded Matlab functions.
Furthermore...
Is it a good idea to replace normal (vars in same dimension) element-by-element operation with bsxfun?
Below is the result of my test. Please find test code in Appendix 2.
As shown in the graph, there is no need to replace normal element-by-element operation with bsxfun.
Appendix 1.
Comparison of bsxfun and repmat.
clear;
k = 1;
a = ones(10,1);
bsxf_result = zeros(n,1);
for i = 1:n;
r = rand(1,i*k);
for it = 1:num_repeat;
tic,
x = bsxfun(@plus,a,r);
tt(it) = toc;
end;
bsxf_result(i) = mean(tt) / n;
for it = 1:num_repeat;
tic,
y = repmat(a,1,i*k)+repmat(r,10,1);
tt(it) = toc;
end;
repmat_result(i) = mean(tt) / n;
end
hold on
plot(repmat_result,'-b')
legend('bsxfun','repmat')
xlabel('Complexity')
ylabel('Speed')
title('Speed test of element-by-element binary operation')
Appendix 2.
Comparison of normal binary operation and bsxfun.
clear;
n = 300;
k = 1;
repmat_result = zeros(n,1);
bsxf_result = zeros(n,1);
num_repeat = 100;
tt = zeros(num_repeat,1);
for i = 1:n;
r = rand(k,i*k);
for it = 1:num_repeat;
tic,
x = bsxfun(@plus,r,r);
tt(it) = toc;
end;
bsxf_result(i) = mean(tt) / n;
for it = 1:num_repeat;
tic,
y = r+r;
tt(it) = toc;
end;
repmat_result(i) = mean(tt) / n;
plot(bsxf_result,'-r')
hold on
plot(repmat_result,'-b')
k = 1;
bsxf_result = zeros(n,1);
for i = 1:n;
r = rand(k,i*k);
for it = 1:num_repeat;
tic,
x = bsxfun(@plus,r,r);
tt(it) = toc;
end;
bsxf_result(i) = mean(tt) / n;
for it = 1:num_repeat;
tic,
y = r+r;
tt(it) = toc;
end;
repmat_result(i) = mean(tt) / n;
end
hold on
plot(repmat_result,'-b')
legend('bsxfun','+')
xlabel('Complexity')
ylabel('Speed')
title('Speed test of element-by-element binary operation')