'Long-runtime problem', improve code, partial sums.
1 view (last 30 days)
Show older comments
Hello, i am using Matlab R2019a and i am trying to make a video of the dynamics of the partial sums of the Riemman Zeta function using matlab plot frames.
I have a few problems:
1) Memory grows until matlab crash before 2 or 5 hours depending on the size.
2)Slow execution , i tried to vectorize the code but due to the size I must use loops to not overflow the memory, the goal is n=500k.
I am looking for some way to improve the code or look for...something more efficient to carry out the task.
Thanks
n=50000;%The sum will be from 1 to n
m=1:1:n;%vector from 1 to n
partes=80;% divide the calculations in 'partes' parts
na=2;%the real part of 's' will be from 0 to 1 in na parts
b=10;%the imaginary part of 's' will be from 0 to b
nb=50;%imaginary part from 0 to b and nb steps
f=zeros(1,length(m));%preallocate
M=zeros(n/partes,1);%preallocate
CS=zeros(n/partes,n);%preallocate
count=0;%savenamecount...
for u=1:1:na%loop real part
for j=1:b*nb% loop imaginary part
tic
f=(exp(-1i*(j/nb)*log(m))./((m).^(u/na))).';%array with each value of the n component of the sum
for pp=0:partes-1%divide the (n,n) matrix into (n/partes,n)
CS=partess(partes,n,pp);%Generate parts of the full matrix
M=CS*f;%matrix*vector
%------plots--------
plot([-10;10],[0;0],'g');
hold on;
plot([0;0],[-10;10],'g');
axis([-10 10 -10 10]);
xlabel 'n';
xlabel 'real';
ylabel 'imag';
title({ ['n=' ,num2str(n)];['a=',num2str(u/na)];['b=' ,num2str(j/nb)]});
grid 'on';
grid 'minor';
plot(real(M),imag(M),'o','MarkerSize',1.5,'MarkerFaceColor','r','MarkerEdgeColor','r');
hold on;
plot(real(M),imag(M),'b');
set(gca,'color','k');
end
plot(real(M(n/partes)),imag(M(n/partes)),'o','MarkerSize',1.5,'MarkerFaceColor','g','MarkerEdgeColor','w');
drawnow;
clf;
cla;
%-----save the frame------
count=count+1;
temp=['~/matlab/imagenes/zeta/videos/frames/','zeta','-',num2str(count),'.jpg'];
saveas(gcf,temp)
toc
end
end
partess:
function C=partess(partes,n,pp)
C=zeros(n/partes,n);
for i=1:n/partes;
for k=1:n
if i>=k-(n/partes)*pp
C(i,k)=1;
end
end
end
0 Comments
Answers (1)
Steven Lord
on 8 Sep 2019
n=50000;%The sum will be from 1 to n
m=1:1:n;%vector from 1 to n
partes=80;% divide the calculations in 'partes' parts
na=2;%the real part of 's' will be from 0 to 1 in na parts
b=10;%the imaginary part of 's' will be from 0 to b
nb=50;%imaginary part from 0 to b and nb steps
f=zeros(1,length(m));%preallocate
M=zeros(n/partes,1);%preallocate
CS=zeros(n/partes,n);%preallocate
These last three lines aren't necessary. You're performing non-subscripted assignment to f, M, and CS in the loops which overwrite the vectors/matrices you've created here.
for u=1:1:na%loop real part
So the outermost loop runs 2 iterations
for j=1:b*nb% loop imaginary part
This one runs 500.
tic
f=(exp(-1i*(j/nb)*log(m))./((m).^(u/na))).';%array with each value of the n component of the sum
for pp=0:partes-1%divide the (n,n) matrix into (n/partes,n)
This one runs 80.
CS=partess(partes,n,pp);%Generate parts of the full matrix
M=CS*f;%matrix*vector
%------plots--------
plot([-10;10],[0;0],'g');
This line of code gets executed 2*500*80 = 80000 times, creating the same line each time! While you won't see any difference, each line is a separate object in memory. Move this outside the loops so it runs only once.
hold on;
plot([0;0],[-10;10],'g');
axis([-10 10 -10 10]);
xlabel 'n';
xlabel 'real';
ylabel 'imag';
These lines should be outside the loop as well, since they don't depend on any of your loop variables.
title({ ['n=' ,num2str(n)];['a=',num2str(u/na)];['b=' ,num2str(j/nb)]});
grid 'on';
grid 'minor';
plot(real(M),imag(M),'o','MarkerSize',1.5,'MarkerFaceColor','r','MarkerEdgeColor','r');
hold on;
plot(real(M),imag(M),'b');
Rather than replotting these lines (adding two new line objects to your axes each and every iteration of your inner loop) you probably want to call plot with an output argument before the loop (plotting NaN vectors of the correct size) and update the XData and YData properties of those lines inside the loop. That way you only have one or two lines that keep getting reused rather than creating tens of thousands of lines stacked on top of one another. This is one of the techniques described in the animation section of the documentation.
set(gca,'color','k');
Outside the loops. Generally, if a section of your code doesn't depend on the loop variables, it probably shouldn't be inside the loops. [One exception is the drawnow statement you have a couple lines down in the code. Leave that to give MATLAB an opportunity to update the graphics with the new data.]
end
plot(real(M(n/partes)),imag(M(n/partes)),'o','MarkerSize',1.5,'MarkerFaceColor','g','MarkerEdgeColor','w');
drawnow;
%-----save the frame------
temp=['~/matlab/imagenes/zeta/videos/frames/','zeta','-',num2str(count),'.jpg'];
saveas(gcf,temp)
This line is only inside two of your three loops, meaning it only runs 1000 times. This is probably still going to be a bottleneck, but if you want each of your images saved it's an unavoidable one.
Except ... this is the only place in your code count is referenced. I assume you cut out some code when you posted it that created and initialized the count variable and updated it inside the middle loop? If not you could simplify this code a whole lot by simply running the body of the middle loop once for the last element of the vectors over which the two outermost loops iterate.
toc
end
end
3 Comments
Steven Lord
on 9 Sep 2019
So I see you're using clf and cla in your updated code. That means you're not actually creating thousands and thousands of line objects, but you are recreating the same lines (visually) over and over. Rather than clearing the figure and axes, if you call plot with an output argument you could delete those output arguments to eliminate just the lines being plotted, leaving these axes lines in place. That would save you the time to clear the figure and axes, replot the lines in the axes, and reconfigure the axes each time.
Actually, now that I see the movie, there are easier ways to achieve your goal. When you create your axes, set its XAxisLocation and YAxisLocation properties each to 'origin' rather than their default values of 'bottom' and 'left' respectively. Just like the plot function accepts property names 'MarkerSize', 'MarkerFaceColor', and 'MarkerEdgeColor' the axes function accepts property names 'XAxisLocation' and 'YAxisLocation'.
Alternately, if you need the lines and the tick labels to be different colors you could use the xline and yline functions to simulate axis lines through the origin.
See Also
Categories
Find more on Annotations in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!