How to convert a nested loop into parfor loop

2019-09-21 16:53发布

问题:

This is my from my MATLAB script.

function [ Im ] = findBorders( I )


Im = false(size(I));

I = padarray(I, [1, 1], 1);
[h w] = size(Im);

bkgFound = false;
for row = 1 : h
    for col = 1 : w
        if I(row + 1, col + 1)

            bkgFound = false;
            for i = 0:2
                for j = 0:2
                    if ~I(row + i, col + j)
                        Im(row, col) = 1;
                        bkgFound = true;
                        break;
                    end;
                end;

                if bkgFound
                    break;
                end;
            end;
        end;
    end;
end;

end

So, I need to convert it to parfor loop, to run into GPU.

I need help. I read some articles, but have no idea about how to convert this.

回答1:

In MATLAB, parfor doesn't allow for things to run on the GPU. The best way to interface with the GPU through MATLAB is to convert your data to a gpuArray and then all operations performed on that data that are optimized for the GPU will be optimized there.

As @Daniel stated, the code that you have posted 1) is not ideal for any sort of parallel processing and 2) could likely be sped up only through vectorization.

I'm not entirely sure what you're trying to do, but it seems like you're trying to find pixels within an image that are surrounded by "not-background". For this I would usually use 2D convolution with a neighborhood kernel to figure out how many neighbors of a given value a pixel has.

For example, the following code locates any pixel which is itself false and completely surrounded by false values (assuming your input image is a logical)

I = [...
    1 1 1 1 0;
    1 0 0 0 0;
    0 0 0 0 0;
    0 0 0 0 0;
    0 0 0 1 1;
    0 0 0 1 0;
];

surrounded_by_zeros = conv2(double(I), ones(3), 'same') == 0

surrounded_by_zeros =

    0 0 0 0 0
    0 0 0 0 0
    0 0 1 1 1
    1 1 0 0 0
    1 1 0 0 0
    1 1 0 0 0

I personally like this solution, but if you have the Image Processing Toolbox, you can also use imerode or imdilate to basically do the same thing.

surrounded_by_zeros = ~imdilate(I, ones(3));
surrounded_by_zeros = imerode(~I, ones(3));

If for some reason you really needed to move this calculation to the GPU (you don't), you could cast this as a gpuArray and then perform the same operation and it would use the GPU behind the scenes

I = gpuArray(I);
surrounded_by_zeros_on_gpu = conv2(double(I), ones(3), 'same') == 0;

Keep in mind that this has the overhead of copying I over to the GPU which for large enough images can be a significant performance hit.