How do I convert my nested for loop into a nested parfor loop?

I have a 36x34x8812 hourly current data called tpres3d. I used the matlab toolbox t_tide from Rich Pawlowicz toolbox to separate tidal currents. Since my data is a 3D array. I used a nested for loop that works but is taking too long to finish. I use the parallel computing toolbox and incorporate a parfor loop to speed up the process. My problem is I don't know how to properly write a parfor loop from a normal for loop. When I use this code:
tpres3d = tpres_U + tpres_V*sqrt(-1) %36x34x8812
[a,b,c] = size(tpres3d)
Ttides_hfdr = NaN*ones(a,b,c)
parfor i = 1:a
for j = 1:b
t0=squeeze(tpres3d(i,j,:));
I=find(~isnan(t0));
if ~isempty(I)
try
[~,~,~,tide_hfdr]=t_tide(t0, ...
'interval',1, ...
'start time',ttime(1), ...
'latitude',y, ...
'rayleigh',constituents, ...
'synthesis',0);
catch
end
end
end
Ttides_hfdr(i,j,:)=tide_hfdr
end
It gives a warning:
Warning: The temporary variable 'tide_hfdr' will be cleared at the beginning of each iteration of the
parfor-loop. If 'tide_hfdr' is used before it is set, a runtime error will occur. For more information,
see Parallel for Loops in MATLAB, "Uninitialized Temporaries".
and an error:
Error: When indexing the sliced variable 'Ttides_hfdr' with the nested for-loop variable 'j', the sliced
variable must be inside a for-loop that defines the range of the for-loop variable. For more information,
see Parallel for Loops in MATLAB, "Nested for-Loops with Sliced Variables".
Trust me, I read the guides and tried it out but I can't seem to grasp how to fix my code. Please help. Thank you.

Answers (1)

One way:
tpres3d = tpres_U + tpres_V*sqrt(-1); %36x34x8812
[a,b,c] = size(tpres3d);
T0=reshape(tpres3D,[],c).';
Ttides_hfdr = nan(size(T0));
ttime1=ttime(1);
parfor k=1:width(T0)
t0=T0(:,k);
if any(~isnan(t0))
try
[~,~,~,tide_hfdr]=t_tide(t0, ...
'interval',1, ...
'start time',ttime1, ...
'latitude',y, ...
'rayleigh',constituents, ...
'synthesis',0);
catch
end
end
Ttides_hfdr(:,k)=tide_hfdr;
end
Ttides_hfdr=reshape(Ttides_hfdr.',[a,b,c]);

11 Comments

Thank you for replying. It still gives the warning:
Warning: The temporary variable 'tide_hfdr' will be cleared at the beginning of each
iteration of the parfor-loop. If 'tide_hfdr' is used before it is set, a runtime error
will occur. For more information, see Parallel for Loops in MATLAB, "Uninitialized
Temporaries".
And a new error:
Error using script_name
The source code
(C:\...\script_name.m)
for the parfor-loop that is trying to execute on the worker could not be found.
Caused by:
Unrecognized function or variable 'tide_hfdr'.
Error using parallel.internal.parfor.cppRemoteParallelFunction
Worker unable to find file.
Unrecognized function or variable 'tide_hfdr'.
You do not set tide_hdfr in your catch block. If this were a serial loop then in this iteration if catch occurred then tide_hdfr would have been set by a previous iteration. But in parfor the previous iteration might or might not exist or might be for a completely unrelated iteration.
You need to set tide_hdfr in your catch block.
Can you give me an example on how do I set it up in my catch block?
Is this what you mean on setting it up inside the catch block? I got no errors but Ttides_hfdr gave me NaNs as result. I'm starting to think that parallel computing does not support t_tide at all.
tpres3d = tpres_U + tpres_V*sqrt(-1); %36x34x8812
[a,b,c] = size(tpres3d);
T0=reshape(tpres3d,[],c).';
Ttides_hfdr = nan(size(T0));
ttime1=ttime(1);
parfor k=1:width(T0)
t0=T0(:,k);
if any(~isnan(t0))
try
[~,~,~,tide_hfdr]=t_tide(t0, ...
'interval',1, ...
'start time',ttime1, ...
'latitude',y, ...
'rayleigh',constituents, ...
'synthesis',0);
Ttides_hfdr(:,k)=tide_hfdr;
catch
end
end
end
Ttides_hfdr=reshape(Ttides_hfdr.',[a,b,c]);
See if the t_tide() is ever getting executed, e.g., using,
tpres3d = tpres_U + tpres_V*sqrt(-1); %36x34x8812
[a,b,c] = size(tpres3d);
T0=reshape(tpres3d,[],c).';
Ttides_hfdr = nan(size(T0));
ttime1=ttime(1);
fails=0;
parfor k=1:width(T0)
t0=T0(:,k);
if any(~isnan(t0))
try
[~,~,~,tide_hfdr]=t_tide(t0, ...
'interval',1, ...
'start time',ttime1, ...
'latitude',y, ...
'rayleigh',constituents, ...
'synthesis',0);
Ttides_hfdr(:,k)=tide_hfdr;
catch
fails=fails+1;
end
else
fails=fails+1;
end
end
Ttides_hfdr=reshape(Ttides_hfdr.',[a,b,c]);
disp("Failures occurred "+fails/a/b*100+" percent")
Failures occurred 26.7974 percent
If so, you shouldn't be getting Ttides_hfdr=nan all the time. That would seem to imply that t_tide() is always returning NaNs.
I agree. Maybe tide_hfdr gets deleted right away each iteration as Ttides_hfdr seems to fail to capture any result at all. I just ran a normal for loop, and it's still ongoing after 24 hours!
Thanks for trying to help, Matt. I appreciate it.
Just run your original loop until a combination of i,j giving a non-trivial tide_hfdr is found. Then it will be easier -- we just need to compare and troubleshoot the two versions for that particular (i,j),
for i = 1:a
for j = 1:b
t0=squeeze(tpres3d(i,j,:));
if ~all(isnan(t0))
try
[~,~,~,tide_hfdr]=t_tide(t0, ...
'interval',1, ...
'start time',ttime(1), ...
'latitude',y, ...
'rayleigh',constituents, ...
'synthesis',0);
if any(isfinite(tide_hfdr));
disp 'Located'
i,j
break;
end
catch
end
end
end
end
I just ran the script you provided. I should store each (i, j) right?
There should only be one (i,j). You should also store the t0 and tide_hfdr that correspond to it.

Sign in to comment.

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Asked:

on 16 Dec 2024

Edited:

on 18 Dec 2024

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!