MATLAB: How to speed up surf plot for thousands of objects

3d surf parallel computing

I want to plot thousands of objects in 3d using surf plot. My code looks like this
% src is an m x 3 matrix. Each row is the x, y and z coordinate of an object.
[sx, sy, sz] = sphere;
for ii = 1 : length(src)
surf(sx+src(ii,1), sy+src(ii,2), sz+src(ii,3))
end
There are up to 3000 objects that I want to plot and it takes roughly 30 secs to render. I'm wondering if there is any way to speed this up? I tried very naively with parfor, which ended up with nothing at all. I'm also wondering why parfor won't work?

Best Answer

Actually the number of points in the surface is probably not a major factor here. That's because the default 20x20 is small enough that, on most systems the bottleneck is going to be surface object creation (which scales with # of objects) rather than updating (which scales with the # of points in the surface).
But the best approach is to start with the sort of scaling analysis I described in this blog post .
Here's a code snippet which you can use for measuring this on your system. Just replace my call to surface with whatever you're doing.
sphere_sizes = [10 15 20 30];
object_counts = [30, 55, 100, 177, 300, 550, 1000, 1771, 3000];
results = zeros(length(sphere_sizes),length(object_counts));
for i1=1:length(sphere_sizes)
npts = sphere_sizes(i1);
for i2=1:length(object_counts)
nobj=object_counts(i2);
cla reset
drawnow
src = randn(nobj,3);
[sx,sy,sz] = sphere(npts);
tic
for ii=1:nobj
surface(sx+src(ii,1),sy+src(ii,2),sz+src(ii,3), ...
'EdgeColor','none','FaceColor',rand(1,3))
end
drawnow
dt = toc;
results(i1,i2) = dt;
disp([num2str(dt), ' for ', num2str(nobj), ' pts'])
end
end
cla reset
hold on
for i1=1:size(results,1)
plot(object_counts,results(i1,:), ...
'DisplayName',[num2str(sphere_sizes(i1)), ' points']);
end
legend('show','Location','NorthWest');
set(gca,'YScale','log')
As you can see by running this, there isn't much of a difference until you get past 20.
Now start modifying this to try different settings and see what works well for your situation. You'll notice that in my example, I turned off the edges and use the surface command instead of the surf command.
I often turn off the edges in cases like this because they don't really add a lot to the appearance and they do have a cost per object.
The surface command is more appropriate in this case because it has lower object creation time. The surf command is really designed for creating simple surface plots and it spends quite a bit initializing support for things like data sources.
As for parfor, unfortunately we can't do object creation in parallel yet, so that doesn't help.