How to convert a nested loop into parfor loop - performance

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.

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.

Related

Quick way of finding complementary vectors in MATLAB

I have a matrix of N rows of binary vectors, i.e.
mymatrix = [ 1 0 0 1 0;
1 1 0 0 1;
0 1 1 0 1;
0 1 0 0 1;
0 0 1 0 0;
0 0 1 1 0;
.... ]
where I'd like to find the combinations of rows that, when added together, gets me exactly:
[1 1 1 1 1]
So in the above example, the combinations that would work are 1/3, 1/4/5, and 2/6.
The code I have for this right now is:
i = 1;
for j = 1:5
C = combnk([1:N],j); % Get every possible combination of rows
for c = 1:size(C,1)
if isequal(ones(1,5),sum(mymatrix(C(c,:),:)))
combis{i} = C(c,:);
i = i+1;
end
end
end
But as you would imagine, this takes a while, especially because of that combnk in there.
What might be a useful algorithm/function that can help me speed this up?
M = [
1 0 0 1 0;
1 1 0 0 1;
0 1 1 0 1;
0 1 0 0 1;
0 0 1 0 0;
0 0 1 1 0;
1 1 1 1 1
];
% Find all the unique combinations of rows...
S = (dec2bin(1:2^size(M,1)-1) == '1');
% Find the matching combinations...
matches = cell(0,1);
for i = 1:size(S,1)
S_curr = S(i,:);
rows = M(S_curr,:);
rows_sum = sum(rows,1);
if (all(rows_sum == 1))
matches = [matches; {find(S_curr)}];
end
end
To display your matches in a good stylized way:
for i = 1:numel(matches)
match = matches{i};
if (numel(match) == 1)
disp(['Match found for row: ' mat2str(match) '.']);
else
disp(['Match found for rows: ' mat2str(match) '.']);
end
end
This will produce:
Match found for row: 7.
Match found for rows: [2 6].
Match found for rows: [1 4 5].
Match found for rows: [1 3].
In terms of efficiency, in my machine this algoritm is completing the detection of matches in about 2 milliseconds.

How to generate a matrix with a function pattern?

Background info (Optional reading):
I'm running simulations of reflections of sound waves in against boundaries. The medium conditions for the points in space are set using a matrix. Let's say the dimensions of the space is an N by N grid, and there are two speeds of sound I care about, c0 and c1.
Right now I'm using code like the following to generate barrier patterns
medium.sound_speed = c0*ones(N,N); % set the speed of sound to be c0 everywhere
medium.sound_speed(:, N/2:N) = c1; % set the right half of the grid to a different speed
medium.sound_speed(50:70, 50:70) = c1; % set a box to have a different speed
Or
% set all speeds to c0 except set the diagonal to c1
medium.sound_speed = c0*ones(N,N)-(c0*eye(N,N))+c1*eye(N,N);
However, I can't generate more complex boundaries with different curvatures.
Question
I want to programmatically create matrices with patterns reflecting functions. For instance, I want to enter f(x)=2 and for that to create a matrix that looked something like this, assuming N=6.
[ 0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
1 1 1 1 1 1
0 0 0 0 0 0
0 0 0 0 0 0 ]
Or f(x)=0.5*x+1
[ 0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 1 1
0 0 1 1 0 0
1 1 0 0 0 0
0 0 0 0 0 0]
I would also be able to generate curved patterns like f(x)=1/x, which seems to require some form of the Midpoint circle algorithm, used for drawing curvatures with pixels.
[ 1 0 0 0 0 0
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 1 0 0
0 0 0 0 1 1
0 0 0 0 0 0 ]
In reality, N is at least 128, so manually creating these matrices for shapes with some level of complexity is impractical, and I thought this was an interesting problem.
Does anyone know of some way to do this, or suggestions for alternative approaches?
Thank you in advance.
Edit:
I modified this implementation of Bresenham's algorithm to provide a matrix with the desired line given an origin and an ending point.
function M=bresenham_line(point)
if (abs(point(4)-point(2)) > abs(point(3)-point(1))) % If the line is steep
x0 = point(2);y0 = point(1); x1 = point(4);y1=point(3);% then it would be converted to
token =1; % non steep by changing coordinate
else
x0 = point(1);y0 = point(2); x1 = point(3);y1=point(4);
token = 0;
end
if(x0 >x1)
temp1 = x0; x0 = x1; x1 = temp1;
temp2 = y0; y0 = y1; y1 = temp2;
end
dx = abs(x1 - x0) ; % Distance to travel in x-direction
dy = abs(y1 - y0); % Distance to travel in y-direction
sx = sign(x1 - x0); % sx indicates direction of travel in X-dir
sy = sign(y1 - y0); % Ensures positive slope line
x = x0; y = y0; % Initialization of line
param = 2*dy - dx ; % Initialization of error parameter
for i = 0:dx-1 % FOR loop to travel along X
x_coord(i+1) = x; % Saving in matrix form for plot
y_coord(i+1) = y;
param = param + 2*dy; % parameter value is modified
if (param >0) % if parameter value is exceeded
y = y +1*sy; % then y coordinate is increased
param = param - 2*(dx ); % and parameter value is decreased
end
x = x + 1*sx; % X-coordinate is increased for next point
end
M = zeros(size(x_coord,2), size(y_coord,2));
for i=1:1:size(x_coord,2)
x = x_coord(i);
y = y_coord(i);
M(x,y) = 1;
end
M
Implemented like so:
c1 = 0;
M = bresenham_line([1 1 Nx/2+1 Ny+1]);
medium.sound_speed = c0*ones(Nx,Ny) - (c0*M) + c1*M;
No progress on curved function shapes yet.
A way to get some similar results:
f = #(x)0.5*x; %create the function (x should be written even if the function doesn't depend on x: #(x) 0*x + 2)
N = 6; %choose the size of the atrix
M = zeros(N,N); %create an empty matrix
x = (1:N);
y = round(f(x-1)); %discretization
x(y>N-1|y<0) = [];
y(y>N-1|y<0) = [];
M(sub2ind(size(M),y+1,x)) = 1;
M = flipud(M)
So you can choose your function, then the result in your matrix will look like a discretization of a normal plot.
This is a slightly 'dirty' way of getting something like this, although I you best bet might Bresenham's algorithm.
N = 128;
[X,Y] = meshgrid(1:N,1:N);
bound1 = Y<2*X;
bound2 = Y<2*X+1;
M = xor(bound1,bound2);
bound1 you can define any function y=f(x), and mark the area under it. with bound2 you select and area that is slightly higher (shifted up). Once you take and xor of the two area you get just the desired y=f(x) marked. I think that in order to get reasonable results the shift might be different for more complicated function.
For illustration I used imagesc (the flipud is just for make the (0,0) in the bottom left, instead of the top left):
imagesc(flipud(M));
Edit
Indeed for some function this might not be the best. For example for y=x^2, you have to increase the shift and still does not look great.
bound1 = Y<X.^2;
bound2 = Y<X.^2+15;
M = xor(bound1,bound2);

How to reorder a binary matrix such that at least '1' value in the column

I have a binary matrix A as
A=[0 0 0 1
0 1 1 0;
0 1 0 1;
0 0 0 1;
0 1 1 1]
I want to reorder the matrix A such that at least 1 column has '1' values. So, the matrix A will be come
%% switch first col and last col in the first row
A=[1 0 0 0
0 1 1 0;
0 1 0 1;
0 0 0 1;
0 1 1 1]
Now, A is satified the above condition. Is it possible to implement it in MATLAB? Thank all
Second example
A=[1 0 0 1;
0 0 1 1;
0 0 0 1]
Then result is
A=[1 0 0 1;
0 1 1 0; %% second and fourth col is switched
0 0 0 1]
Update: what is happen if the row of A is comming on fly. It means that at t=0, the first row comes and A=[1 0 0 1]. Then next time, the second row comes. The matrix A will be A=[1 0 0 1; 0 0 1 1]. Then the algorithm will be check here because the second col. of A is zero. Performs switching and then next col of A comes, so on. Could you design help me the implementation for that task?
Simple deterministic strategy, start from the top left, fill as many columns as you can with the first row, then continue with the next row and the next columns. For the remaining rows, just start over at the first column.
%Get rows in which ones can be found.
[~,r]=find(A.');
%Assign new column values for the ones
c=mod(0:numel(r)-1,size(A,2))+1;
B=zeros(size(A));
B(sub2ind(size(A),r(:),c(:)))=1;
I guess this would do (at least for tall matrices)
for ind = 1:min(size(A))
t = A(ind,:);
A(ind,:) = circshift(t,[0 -(find(t)-ind)]);
end
I found the dumbest way to do this :D
A=[0 0 0 1
0 1 1 0;
0 1 0 1;
0 0 0 1;
0 1 1 1];
while ~(any(A(:,1)) && any(A(:,2)) && any(A(:,3)) && any(A(:,4)))
for ii = 1:length(A(:,1))
A(ii,:) = A(ii,randperm(4,4));
end
end
disp(A)
The code checks each column in A to have 1. If not, it randomly shifts rows in A and repeats until the requirement is satisfied.

Comparing Two Matrices in MATLAB which shows how much they are matched

Please assume A is a matrix of 4 x 4 which has:
A = 1 0 1 0
1 0 1 0
1 1 1 0
1 1 0 0
And B is a reference matrix (4 x 4) which is:
B = 1 0 1 0
1 0 1 0
1 0 1 0
1 1 1 0
Now, if A would be compared to B which is the reference matrix, by matching these two matrices, almost all of members are equal except A(4,3) and A(3,2). However, since B is the reference matrix and A is comparing to that, only differences of those members are matter which are 1 in B. In this particular example, A(4,3) is only matter, not A(3,2), Means:
>> C = B ~= A;
ans =
0 0 0 0
0 0 0 0
0 1 0 0
0 0 1 0
A(4,3) ~= B(4,3)
Finally, we are looking for a piece of code which can show how many percentage of ones in A are equal to their equivalent members at B. In this case the difference is:
(8 / 9) * 100 = 88.89 % are matched.
Please bear in mind that speed is also important here. Therefore, quicker solution are more appreciated. Thanks.
For getting only the different entries where there is a 1 in B, just add an & to it, so you'll only get these entries. To get the percentage, take the sum where A and B are 1. Then divide it by the sum of 1 in B (or the sum of 1in A -> see the note below).
A = [1 0 1 0;
1 0 1 0;
1 1 1 0;
1 1 0 0];
B = [1 0 1 0;
1 0 1 0;
1 0 1 0;
1 1 1 0];
C = (B ~= A) & B
p = sum(B(:) & A(:)) / sum(B(:)) * 100
This is the result:
C =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 1 0
p =
88.8889
Edit / Note: In the OP's question it's not 100% clear if he wants the percentage in relation to the sum of ones in A or B. I assumed that it is a percentage of the reference-matrix, which is B. Therefore I divide by sum(B(:)). In case you need it in reference to the ones in A, just change the last line to:
p = sum(B(:) & A(:)) / sum(A(:)) * 100
If I got it right, what you want to know is where B == 1 and A == 0.
Try this:
>> C = B & ~A
C =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 1 0
To get the percentage, you could try this:
>> 100 * sum(A(:) & B(:)) / sum(A(:))
ans =
88.8889
You can use matrix-multiplication, which must be pretty efficient as listed next.
To get the percentage value with respect to A -
percentage_wrtA = A(:).'*B(:)/sum(A(:)) * 100;
To get the percentage value with respect to B -
percentage_wrtB = A(:).'*B(:)/sum(B(:)) * 100;
Runtime tests
Here's some quick runtime tests to compare matrix-multiplication against summation of elements with (:) and ANDing -
>> M = 6000; %// Datasize
>> A = randi([0,1],M,M);
>> B = randi([0,1],M,M);
>> tic,sum(B(:) & A(:));toc
Elapsed time is 0.500149 seconds.
>> tic,A(:).'*B(:);toc
Elapsed time is 0.126881 seconds.
Try:
sum(sum(A & B))./sum(sum(A))
Output:
ans =
0.8889

Efficiently unpack a vector into binary matrix Octave

On Octave I'm trying to unpack a vector in the format:
y = [ 1
2
4
1
3 ]
I want to return a matrix of dimension ( rows(y) x max value(y) ), where for each row I have a 1 in the column of the original digits value, and a zero everywhere else, i.e. for the example above
y01 = [ 1 0 0 0
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0 ]
so far I have
y01 = zeros( m, num_labels );
for i = 1:m
for j = 1:num_labels
y01(i,j) = (y(i) == j);
end
end
which works, but is going get slow for bigger matrices, and seems inefficient because it is cycling through every single value even though the majority aren't changing.
I found this for R on another thread:
f3 <- function(vec) {
U <- sort(unique(vec))
M <- matrix(0, nrow = length(vec),
ncol = length(U),
dimnames = list(NULL, U))
M[cbind(seq_len(length(vec)), match(vec, U))] <- 1L
M
}
but I don't know R and I'm not sure if/how the solution ports to octave.
Thanks for any suggestions!
Use a sparse matrix (which also saves a lot of memory) which can be used in further calculations as usual:
y = [1; 2; 4; 1; 3]
y01 = sparse (1:rows (y), y, 1)
if you really want a full matrix then use "full":
full (y01)
ans =
1 0 0 0
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0
Sparse is a more efficient way to do this when the matrix is big.
If your dimension of the result is not very high, you can try this:
y = [1; 2; 4; 1; 3]
I = eye(max(y));
y01 = I(y,:)
The result is same as full(sparse(...)).
y01 =
1 0 0 0
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0
% Vector y to Matrix Y
Y = zeros(m, num_labels);
% Loop through each row
for i = 1:m
% Use the value of y as an index; set the value matching index to 1
Y(i,y(i)) = 1;
end
Another possibility is:
y = [1; 2; 4; 1; 3]
classes = unique(y)(:)
num_labels = length(classes)
y01=[1:num_labels] == y
With the following detailed printout:
y =
1
2
4
1
3
classes =
1
2
3
4
num_labels = 4
y01 =
1 0 0 0
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0

Resources