Parfor "Out of Memory during deserialization" in large matrix operations

31 views (last 30 days)
I am trying to use parfor for a large matrix operation. I am getting Out of Memory during deserialization error. Is there a way to minimize the memory? Below is the minimal example code:
clc; clear;
warpedImages = num2cell(uint8(randi([0,255], 1654, 6288, 3, 35)),1:3);
warpedImages = reshape(warpedImages,1,[]);
% Initialze
n = length(warpedImages);
sigmaN = 10;
sigmag = 0.1;
panoramasize = size(warpedImages{1});
Amat = cell(n);
Bvec = zeros(n,1);
IuppeIdx = nonzeros(triu(reshape(1:numel(Amat), size(Amat))));
Amat_temp = cell(1,length(IuppeIdx));
matSize = size(Amat);
% 4D warped images (Slicing)
wim_4d = cell2mat(reshape(warpedImages,1,1,1,[]));
% Get the Ibarijs and Nijs
parfor i = 1:length(IuppeIdx)
% Index to subscripts
[ii,jj] = ind2sub(matSize, IuppeIdx(i));
if ii == jj
diag_val_1 = 0;
diag_val_2 = 0;
Z = 1:n;
Z(Z==ii) = [];
for d = Z
[Ibarij, Ibarji, Nij] = getIbarNij(panoramasize, wim_4d(:,:,:,ii), wim_4d(:,:,:,d));
diag_val_1 = diag_val_1 + ( (Nij + Nij) .* Ibarij.^2 );
diag_val_2 = diag_val_2 + Nij;
end
diag_val = diag_val_1 + (sigmaN^2/sigmag^2) * diag_val_2;
B_val = (sigmaN^2/sigmag^2) * diag_val_2;
Amat_temp{i} = diag_val;
Bvec(i) = B_val
end
if ii ~= jj
[Ibarij,Ibarji,Nij] = getIbarNij(panoramasize, wim_4d(:,:,:,ii), wim_4d(:,:,:,jj));
Amat_temp{i} = -(Nij+Nij) .* (Ibarij .* Ibarji);
end
end
function [Ibarij,Ibarji,Nij] = getIbarNij(panoramasize, Imij, Imji)
Ibarij = zeros(panoramasize,'uint8');
Ibarji = zeros(panoramasize,'uint8');
% Overlay the warpedImage onto the panorama.
maski = imbinarize(rgb2gray(255 * Imij));
maskj = imbinarize(rgb2gray(255 * Imji));
% Find the overlap mask
Nij_im = maski & maskj;
Nij_im = imfill(Nij_im, 'holes');
Nijidx = repmat(Nij_im, 1, 1, size(Imij,3));
% Get the overlapping region RGB values for two images
Ibarij(Nijidx) = Imij(Nijidx);
Ibarji(Nijidx) = Imji(Nijidx);
% Convert to double
Ibarij_double = double(Ibarij);
Ibarji_double = double(Ibarji);
% Nij
Nij = sum(sum(Nij_im));
% Ibar ijs
Ibarij = reshape(sum(sum(Ibarij_double)) ./ Nij, 1, 3);
Ibarji = reshape(sum(sum(Ibarji_double)) ./ Nij, 1, 3);
% Replace NaNs by zeros
Ibarij(isnan(Ibarij)) = 0;
Ibarji(isnan(Ibarji)) = 0;
end
Line [Ibarij, Ibarji, Nij] = getIbarNij(panoramasize, wim_4d(:,:,:,ii), wim_4d(:,:,:,d)); throws a warning message: The entire array or structure 'wim_4d' is a broadcast variable. This might result in unnecessary communication overhead. I have used ind2sub for getting the subscripts as it is easy to work. However, wim_4d(:,:,:,ii) and others cannot be sliced. Any other suggestion and help is appreciated!

Answers (1)

Namnendra
Namnendra on 26 Jun 2024
Hello Preetham,
I understand that you want to optimize your program by reducing memory usage.
When using `parfor` in MATLAB, one common issue is the memory overhead caused by broadcasting large variables to all workers. In your case, the entire `wim_4d` array is being broadcasted to each worker, which leads to high memory usage and can cause out-of-memory errors.
One way to minimize the memory overhead is to avoid broadcasting large variables and instead use more efficient slicing or data partitioning strategies. Here are a few suggestions to help you reduce memory usage:
1. Precompute Subsets of Data
Instead of passing the entire `wim_4d` array to each worker, you can precompute and pass only the necessary slices of the array.
2. Use `parfor` with Sliced Variables
Ensure that the variables used inside the `parfor` loop are sliced properly. This means that each worker should only work on a subset of the data.
3. Optimize Memory Usage within `parfor`
Minimize the amount of data being passed to and from the workers. Try to reduce the size of intermediate variables and avoid unnecessary copies of data.
Here's a modified version of your code that attempts to address these issues:
clc; clear;
warpedImages = num2cell(uint8(randi([0,255], 1654, 6288, 3, 35)),1:3);
warpedImages = reshape(warpedImages,1,[]);
% Initialize
n = length(warpedImages);
sigmaN = 10;
sigmag = 0.1;
panoramasize = size(warpedImages{1});
Amat = cell(n);
Bvec = zeros(n,1);
IuppeIdx = nonzeros(triu(reshape(1:numel(Amat), size(Amat))));
Amat_temp = cell(1,length(IuppeIdx));
matSize = size(Amat);
% Precompute the necessary slices of wim_4d
wim_4d_slices = cell(1, n);
for i = 1:n
wim_4d_slices{i} = wim_4d(:,:,:,i);
end
% Get the Ibarijs and Nijs
parfor i = 1:length(IuppeIdx)
% Index to subscripts
[ii,jj] = ind2sub(matSize, IuppeIdx(i));
if ii == jj
diag_val_1 = 0;
diag_val_2 = 0;
Z = 1:n;
Z(Z==ii) = [];
for d = Z
[Ibarij, Ibarji, Nij] = getIbarNij(panoramasize, wim_4d_slices{ii}, wim_4d_slices{d});
diag_val_1 = diag_val_1 + ( (Nij + Nij) .* Ibarij.^2 );
diag_val_2 = diag_val_2 + Nij;
end
diag_val = diag_val_1 + (sigmaN^2/sigmag^2) * diag_val_2;
B_val = (sigmaN^2/sigmag^2) * diag_val_2;
Amat_temp{i} = diag_val;
Bvec(i) = B_val;
end
if ii ~= jj
[Ibarij, Ibarji, Nij] = getIbarNij(panoramasize, wim_4d_slices{ii}, wim_4d_slices{jj});
Amat_temp{i} = -(Nij+Nij) .* (Ibarij .* Ibarji);
end
end
function [Ibarij,Ibarji,Nij] = getIbarNij(panoramasize, Imij, Imji)
Ibarij = zeros(panoramasize,'uint8');
Ibarji = zeros(panoramasize,'uint8');
% Overlay the warpedImage onto the panorama.
maski = imbinarize(rgb2gray(255 * Imij));
maskj = imbinarize(rgb2gray(255 * Imji));
% Find the overlap mask
Nij_im = maski & maskj;
Nij_im = imfill(Nij_im, 'holes');
Nijidx = repmat(Nij_im, 1, 1, size(Imij,3));
% Get the overlapping region RGB values for two images
Ibarij(Nijidx) = Imij(Nijidx);
Ibarji(Nijidx) = Imji(Nijidx);
% Convert to double
Ibarij_double = double(Ibarij);
Ibarji_double = double(Ibarji);
% Nij
Nij = sum(sum(Nij_im));
% Ibar ijs
Ibarij = reshape(sum(sum(Ibarij_double)) ./ Nij, 1, 3);
Ibarji = reshape(sum(sum(Ibarji_double)) ./ Nij, 1, 3);
% Replace NaNs by zeros
Ibarij(isnan(Ibarij)) = 0;
Ibarji(isnan(Ibarji)) = 0;
end
I hope the above information helps you.
Thank you.

Products


Release

R2023a

Community Treasure Hunt

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

Start Hunting!