I think this can be optimized by vectorization of the innermost loop.
input = 2*rand(24,24,3)-1;
theta = 2*rand(26,12,3)-1;
output = zeros(20,20,12); % preallocating
temp = zeros(3,12); % preallocating
for i = 1:20
for j = 1:20
for c = 1:3
temp(c,:) = [1, reshape(input(i:i+4,j:j+4,c),1,25)]*theta(:,:,c);
end
output(i,j,:) = sum(temp);
end
end
Any ideas how to do that?
You could replace your inner loop by something like this:
aux = [ones(1,3); reshape(input(i:i+4,j:j+4,:),25,3)];
theta_concat = reshape(permute(theta, [2 1 3]),12,78);
output(i,j,:) = theta_concat*aux(:);
Related
I want to preallocate a matrix in matlab to get rid of out of memory error, but how can i use preallocating for a while loop?
we use preallocating for a for loop like this:
m=10000;
x=zeros(m,1)
for i = 1:m
x(i) = i
end
but what if i want to do this for a while loop
m = 10000
x = 1
i=0
some_criteria = 10
while x<some_criteria
i = i+1
x(i) = i
some_criteria = f(x)
end
try this:
m = 10000
x=zeros([],1);
i=0
some_criteria = 10
while x<some_criteria
i = i+1
x(i,1) = i
some_criteria = f(x)
end
if you write x(i) instead of x(i,1), the result will be a row vector.
I would like to write a Matlab code to calculate the following:
\sum_{k=0}^{N-1} \frac{1}{k!} \sum_{i=0}^{k} {k \choose i}(a-1)^{k-i} a^k
and my code is:
N = 3;
a = [3 4];
for k = 0:N-1
f = 0;
for i = 0:k
f = f + nchoosek(k,i).* a.^k .* (a-1).^(k-i);
end
sumoff = sum(f);
all = (( 1./ (factorial(k))).*sumoff);
end
overall= sum(all);
'all' variable gives different value when it is inside the for loop rather than outside. But I want it to calculate when k = 0:N-1. What am I doing wrong?
Thank you.
The issue is your current code overwrites all on every iteration. Moving it outside the loop also doesn't work because you'll only save the result of the last iteration.
To save the all of every iteration, define all as a vector and then assign each intermediate result into that vector:
N = 3;
a = [3 4];
% preallocate a vector for `all`
all = nan(N-1, 1);
for k = 0:N-1
f = 0;
for i = 0:k
f = f + nchoosek(k,i) .* a.^k .* (a-1).^(k-i);
end
sumoff = sum(f);
% assign your intermediate result into the `all` vector
all(k+1) = ((1./(factorial(k))) .* sumoff);
end
overall = sum(all);
I need to save results of a for loop in a matrix where its size is 4*1?
My function:
function test()
for j=2:2:8
h= 3*j
end
end
results:
h=6
h=12
h=18
h=24
Thank you in advance.
You can do this via loop, and than you should first create the matrix:
function test()
n = 2:2:8;
h = zeros(length(n),1)
counter = 1;
for j = n
h(counter) = 3*j
counter = counter+1;
end
end
But that is the long and non-efficient way, instead you should use vectorization:
n = 2:2:8;
h = n.'*3
or just: h = (2:2:8).'.*3;
that's it.
I am writing a graphical representation of numerical stability of differential operators and I am having trouble removing a nested for loop. The code loops through all entries in the X,Y, plane and calculates the stability value for each point. This is done by finding the roots of a polynomial of a size dependent on an input variable (length of input vector results in a polynomial 3d matrix of size(m,n,(lenght of input vector)). The main nested for loop is as follows.
for m = 1:length(z2)
for n = 1:length(z1)
pointpoly(1,:) = p(m,n,:);
r = roots(pointpoly);
if isempty(r),r=1e10;end
z(m,n) = max(abs(r));
end
end
The full code of an example numerical method (Trapezoidal Rule) is as follows. Any and all help is appreciated.
alpha = [-1 1];
beta = [.5 .5];
Wind = 2;
Wsize = 500;
if numel(Wind) == 1
Wind(4) = Wind(1);
Wind(3) = -Wind(1);
Wind(2) = Wind(4);
Wind(1) = Wind(3);
end
if numel(Wsize) == 1
Wsize(2) = Wsize;
end
z1 = linspace(Wind(1),Wind(2),Wsize(1));
z2 = linspace(Wind(3),Wind(4),Wsize(2));
[Z1,Z2] = meshgrid(z1,z2);
z = Z1+1i*Z2;
p = zeros(Wsize(2),Wsize(1),length(alpha));
for n = length(alpha):-1:1
p(:,:,(length(alpha)-n+1)) = alpha(n)-z*beta(n);
end
for m = 1:length(z2)
for n = 1:length(z1)
pointpoly(1,:) = p(m,n,:);
r = roots(pointpoly);
if isempty(r),r=1e10;end
z(m,n) = max(abs(r));
end
end
figure()
surf(Z1,Z2,z,'EdgeColor','None');
caxis([0 2])
cmap = jet(255);
cmap((127:129),:) = 0;
colormap(cmap)
view(2);
title(['Alpha Values (',num2str(alpha),') Beta Values (',num2str(beta),')'])
EDIT::
I was able to remove one of the for loops using the reshape command. So;
for m = 1:length(z2)
for n = 1:length(z1)
pointpoly(1,:) = p(m,n,:);
r = roots(pointpoly);
if isempty(r),r=1e10;end
z(m,n) = max(abs(r));
end
end
has now become
gg = reshape(p,[numel(p)/length(alpha) length(alpha)]);
r = zeros(numel(p)/length(alpha),1);
for n = 1:numel(p)/length(alpha)
temp = roots(gg(n,:));
if isempty(temp),temp = 0;end
r(n,1) = max(abs(temp));
end
z = reshape(r,[Wsize(2),Wsize(1)]);
This might be one for loop, but I am still going through the same number of elements. Is there a way to use the roots command on all of my rows at the same time?
This is a follow-up question to How to append an element to an array in MATLAB? That question addressed how to append an element to an array. Two approaches are discussed there:
A = [A elem] % for a row array
A = [A; elem] % for a column array
and
A(end+1) = elem;
The second approach has the obvious advantage of being compatible with both row and column arrays.
However, this question is: which of the two approaches is fastest? My intuition tells me that the second one is, but I'd like some evidence for or against that. Any idea?
The second approach (A(end+1) = elem) is faster
According to the benchmarks below (run with the timeit benchmarking function from File Exchange), the second approach (A(end+1) = elem) is faster and should therefore be preferred.
Interestingly, though, the performance gap between the two approaches is much narrower in older versions of MATLAB than it is in more recent versions.
R2008a
R2013a
Benchmark code
function benchmark
n = logspace(2, 5, 40);
% n = logspace(2, 4, 40);
tf = zeros(size(n));
tg = tf;
for k = 1 : numel(n)
x = rand(round(n(k)), 1);
f = #() append(x);
tf(k) = timeit(f);
g = #() addtoend(x);
tg(k) = timeit(g);
end
figure
hold on
plot(n, tf, 'bo')
plot(n, tg, 'ro')
hold off
xlabel('input size')
ylabel('time (s)')
leg = legend('y = [y, x(k)]', 'y(end + 1) = x(k)');
set(leg, 'Location', 'NorthWest');
end
% Approach 1: y = [y, x(k)];
function y = append(x)
y = [];
for k = 1 : numel(x);
y = [y, x(k)];
end
end
% Approach 2: y(end + 1) = x(k);
function y = addtoend(x)
y = [];
for k = 1 : numel(x);
y(end + 1) = x(k);
end
end
How about this?
function somescript
RStime = timeit(#RowSlow)
CStime = timeit(#ColSlow)
RFtime = timeit(#RowFast)
CFtime = timeit(#ColFast)
function RowSlow
rng(1)
A = zeros(1,2);
for i = 1:1e5
A = [A rand(1,1)];
end
end
function ColSlow
rng(1)
A = zeros(2,1);
for i = 1:1e5
A = [A; rand(1,1)];
end
end
function RowFast
rng(1)
A = zeros(1,2);
for i = 1:1e5
A(end+1) = rand(1,1);
end
end
function ColFast
rng(1)
A = zeros(2,1);
for i = 1:1e5
A(end+1) = rand(1,1);
end
end
end
For my machine, this yields the following timings:
RStime =
30.4064
CStime =
29.1075
RFtime =
0.3318
CFtime =
0.3351
The orientation of the vector does not seem to matter that much, but the second approach is about a factor 100 faster on my machine.
In addition to the fast growing method pointing out above (i.e., A(k+1)), you can also get a speed increase from increasing the array size by some multiple, so that allocations become less as the size increases.
On my laptop using R2014b, a conditional doubling of size results in about a factor of 6 speed increase:
>> SO
GATime =
0.0288
DWNTime =
0.0048
In a real application, the size of A would needed to be limited to the needed size or the unfilled results filtered out in some way.
The Code for the SO function is below. I note that I switched to cos(k) since, for some unknown reason, there is a large difference in performance between rand() and rand(1,1) on my machine. But I don't think this affects the outcome too much.
function [] = SO()
GATime = timeit(#GrowAlways)
DWNTime = timeit(#DoubleWhenNeeded)
end
function [] = DoubleWhenNeeded()
A = 0;
sizeA = 1;
for k = 1:1E5
if ((k+1) > sizeA)
A(2*sizeA) = 0;
sizeA = 2*sizeA;
end
A(k+1) = cos(k);
end
end
function [] = GrowAlways()
A = 0;
for k = 1:1E5
A(k+1) = cos(k);
end
end