MATLAB 'parfor' Loops Very Slow When Compared With 'for' loop - matlab

I have a script that I'm running, and at one point I have a loop over n objects, where I want n to be fairly large.
I have access to a server, so I put in a parfor loop. However, this is incredibly slow compared with a standard for loops.
For example, running a certain configuration ( the one below ) with the parfor loop on 35 workers took 68 seconds, whereas the for loop took 2.3 seconds.
I know there's stuff to do with array-broadcasting that can cause issues, but I don't know a lot about this.
n = 20;
r = 1/30;
tic
X = rand([2,n-1]);
X = [X,[0.5;0.5]];
D = sq_distance(X,X);
A = sparse((D < r) - eye(n));
% Infected set I
I = n;
[S,C] = graphconncomp(A);
compnum = C(I);
I_new = find(C == compnum);
I = I_new;
figure%('visible','off')
gplot(A,X')
hold on
plot(X(1,I),X(2,I),'r.')
hold off
title('time = 0')
axis([0,1,0,1])
time = 0;
t_max = 10; t_int = 1/100;
TIME = 1; T_plot = t_int^(-1) /100;
loops = t_max / T_plot;
F(loops) = struct('cdata',[],'colormap',[]);
F(1) = getframe;
% Probability of healing in interval of length t_int
heal_rate = 1/3; % (higher number is faster heal)
p_heal = t_int * heal_rate;
numhealed = 0;
while time < t_max
time = time+t_int;
steps = poissrnd(t_int,[n,1]);
parfor k = 1:n
for s = 1:steps(k)
unit_vec = unif_unitvector;
X_new = X(:,k) + unit_vec*t_int;
if ( X_new < 1 == ones(2,1) ) ...
& ( X_new > 0 == ones(2,1) )
X(:,k) = X_new;
end
end
end
D = sq_distance(X,X);
A = sparse((D < r) - eye(n));
[S,C] = graphconncomp(A);
particles_healed = binornd(ones(length(I),1),p_heal);
still_infected = find(particles_healed == 0);
I = I(still_infected);
numhealed = numhealed + sum(particles_healed);
I_new = I;
% compnum = zeros(length(I),1);
for i = 1:length(I)
compnum = C(I(i));
I_new = union(I_new,find(C == compnum));
end
I = I_new;
if time >= T_plot*TIME
gplot(A,X')
hold on
plot(X(1,I),X(2,I),'r.')
hold off
title(sprintf('time = %1g',time))
axis([0,1,0,1])
% fprintf('number healed = %1g\n',numhealed)
numhealed = 0;
F(TIME) = getframe;
TIME = TIME + 1;
end
end
toc

Related

How do I resolve error "Operator '>' is not supported for operands of type 'function_handle'" in Matlab?

The purpose of this iterative function is to update two parameters of my function to keep output values within a desired range (19 to 21)
Here is what I have so far
for i = 2:tw
T1f(i) = dT1(i,T1(i-1),T2(i-1))+T1(i-1);
T2f(i) = dT2(i,T1(i-1),T2(i-1))+T2(i-1);
if ((T1f(i) > 21) | (T2f(i) > 21)) && dT1f > 0
k2f(i:(i+1799)) = k2f(i)-2;
Qfin(i:(i+1799)) = Qfin(i)-500;
N = N+1;
elseif ((19 > T1f(i)) | (19 > T2f(i))) && 0 > dT1f
k2f(i:i+1799) = k2f(i)+2;
Qfin(i:(i+1799)) = Qfin(i)+500;
N = N+1;
end
k2f = max(k2f,10);
k2f = min(k2f,1);
Qfin = max(Qfin,2500);
Qfin = max(Qfin,0);
end
I keep receiving the error Operator '>' is not supported for operands of type 'function_handle for the elseif line, but not at the if line. Why is this and how to I remedy it? Any suggestions about a better way to acheive this would also be appreciated.
Full file will be below.
k1 = 0.2; %W/m^2
k2 = 1750; % W/m^2, constant
k3 = 0.5; %W/m^2
Ain = 0.5; %m^2
Cair = 1005; %J/kg*K
Pair = 1.2; %kg/m^3
Qin = 2500; %W/m^2 constant
L = 5; %m
W = 6; %m
H = 3; %m H1 = H2 = H
T1o = 5; %C
T2o = 7; %C
N = 1;
% Calculating Areas and volumes
Awalls = 2*((L*H)+(W*H)); %m^2
Aceiling = W*L; %m^2
Aroof = sqrt((W*L)^2+(L*H*2)^2)+W*H; %
Vup = W*H*L/2; %m^3
Vdown = W*H*L; %m^3
%Initializing Arrays and Values
tw = 86400*2; %number of seconds in two days
t = [1:1:tw]; %array with integers 1-tw
n = length(t);
T = zeros(1,n);
T1 = zeros(1,n);
T2 = zeros(1,n);
T1f = zeros(1,n);
T2f = zeros(1,n);
T1(1) = T1o;
T2(1) = T2o;
T1f(1) = T1o;
T2f(1) = T2o;
%% Setting Q values
Qfin = zeros(1,n); %Qin for fluctuation
Qfin(1) = 2500;
%% Setting k2 values
k2f = zeros(1,n); %k3 for fluctuation
kf(1) = 10;
%% Defining Functions
Tout = #(t,T) -10*sin(2*pi*t/86400);
%Constant k2/Qin
dT1 = #(t,T1,T2) ((Ain*Qin)-(Aceiling*k2*(T1-T2-5))-(Awalls*k1*(T1-
Tout(t))))/(Cair*Pair*Vdown);
dT2 = #(t,T1,T2) ((Aceiling*k2*(T1-T2-5))-(Aroof*k3*(T2-Tout(t))))/(Cair*Pair*Vup);
%Fluctuating k2/Qin
dT1f = #(t,T1,T2) ((Ain*Qfin(t))-(Aceiling*k2f(t)*(T1-T2-5))-(Awalls*k1*(T1-
Tout(t))))/(Cair*Pair*Vdown);
dT2f = #(t,T1,T2) ((Aceiling*k2f(t)*(T1-T2-5))-(Aroof*k3*(T2-Tout(t))))/(Cair*Pair*Vdown);
%% Iterate for constant k2/Qin with Euler's
for i = 2:tw
T1(i) = dT1(i,T1(i-1),T2(i-1))+T1(i-1);
T2(i) = dT2(i,T1(i-1),T2(i-1))+T2(i-1);
end
%% Iteratre for fluctuation
for i = 2:tw
T1f(i) = dT1(i,T1(i-1),T2(i-1))+T1(i-1);
T2f(i) = dT2(i,T1(i-1),T2(i-1))+T2(i-1);
if ((T1f(i) > 21) | (T2f(i) > 21)) && dT1f > 0
k2f(i:(i+1799)) = k2f(i)-2;
Qfin(i:(i+1799)) = Qfin(i)-500;
N = N+1;
elseif ((19 > T1f(i)) | (19 > T2f(i))) && 0 > dT1f
k2f(i:i+1799) = k2f(i)+2;
Qfin(i:(i+1799)) = Qfin(i)+500;
N = N+1;
end
k2f = max(k2f,10);
k2f = min(k2f,1);
Qfin = max(Qfin,2500);
Qfin = max(Qfin,0);
end

how to Improve the speed matlab

This is my matlab code. It runs too slow and I had no clue how to improve it.
Could you help me to improve the speed?
What I would like to do is to create some random points and then remove the random points to make them similar to my target points.
syms Dx Dy p q;
a = 0;
num = 10;
x = rand(1,num);
y = rand(1,num);
figure(1)
scatter(x,y,'.','g')
%num_x = xlsread('F:\bin\test_2');% num 1024
%figure(2)
%scatter(num_x(:,1),num_x(:,2),'.','r');
q = 0;
num_q = 10;
x_q = randn(1,num_q);
y_q = randn(1,num_q);
%figure(2)
hold on;
scatter(x_q,y_q,'.','r')
for i = 1:num_q;
for j = 1:num_q;
qx(i,j) = x_q(i) - x_q(j);
qy(i,j) = y_q(i) - y_q(j);
%qx(i,j) = num_x(i,1) - num_x(j,1);
%qy(i,j) = num_x(i,2) - num_x(j,2);
%d~(s(i),s(j))
if ((qx(i,j))^2+(qy(i,j)^2))> 0.01 % find neighbours
qx(i,j) = 0;
qy(i,j) = 0;
end
end
end
for i = 1:num_q;
for j = 1:num_q;
if qx(i,j)>0&&qy(i,j)>0
q = q + exp(-(((Dx - qx(i,j))^2)+((Dy - qy(i,j))^2))/4);%exp(-(((Dx - qx(i,j))^2)+((Dy - qy(i,j))^2))/4);
end
end
end
%I = ones(num,num); % I(s) should from a grayscale image
%r = 1./sqrt(I);
for s = 1:100;
for i = 1:num;
for j = 1:num;
dx(i,j) = x(i) - x(j);
dy(i,j) = y(i) - y(j);
%d~(s(i),s(j))
if ((dx(i,j))^2+(dy(i,j)^2))> 0.05 % delta p, find neighbours
dx(i,j) = 0;
dy(i,j) = 0;
end
end
end
p = 0;
for i = 1:num;
for j = 1:num;
if dx(i,j)>0&&dy(i,j)>0
p = p + exp(-(((Dx - dx(i,j))^2)+((Dy - dy(i,j))^2))/4);
end
end
end
p = p - q;
sum = 0;
for i = 1:num;
for j = 1:num;
if dx(i,j)>0&&dy(i,j)>0;
kx(i,j) = (1/2)*(Dx-dx(i,j))*exp((-(Dx-dx(i,j))^2+(Dy-dy(i,j))^2)/4);
ky(i,j) = (1/2)*(Dy-dy(i,j))*exp((-(Dx-dx(i,j))^2+(Dy-dy(i,j))^2)/4);
end
end
end
sum_x = ones(1,num);% 1行N列0矩阵
sum_y = ones(1,num);
%fx = zeros(1,num);
for i = 1:num;
for j = 1:num;
if dx(i,j)>0&&dy(i,j)>0;
fx(i) = p*kx(i,j);% j is neighbour to i
fy(i) = p*ky(i,j);
%fx(i) = matlabFunction(fx(i));
%fy(i) = matlabFunction(fy(i));
%P =quad2d(#(Dx,Dy) fx,0,0.01,0,0.01);
%fx =quad(#(Dx) fx,0,0.01);
%fx(i) =quad(#(Dy) fx(i),0,0.01);
%Q =quad2d(#(Dx,Dy) fy,0,0.01,0,0.01);
fx(i) = double(int(int(fx(i),Dx,0,0.01),Dy,0,0.01));
fy(i) = double(int(int(fy(i),Dx,0,0.01),Dy,0,0.01));
%fx(i) = vpa(p*kx(i,j));
%fy(i) = vpa(p*ky(i,j));
%fx(i) = dblquad(#(Dx,Dy)fx(i),0,0.01,0,0.01);
%fy(i) = dblquad(#(Dx,Dy)fy(i),0,0.01,0,0.01);
sum_x(i) = sum_x(i) + fx(i);
sum_y(i) = sum_y(i) + fy(i);
end
end
end
for i = 1:num;
sum_x = 4.*sum_x./num;
sum_y = 4.*sum_y./num;
x(i) = x(i) - 0.05*sum_x(i);
y(i) = y(i) - 0.05*sum_y(i);
end
a = a+1
end
hold on;
scatter(x,y,'.','b')
The fast version of your loop should be something like:
qx = bsxfun(#minus, x_q.', x_q);
qy = bsxfun(#minus, y_q.', y_q);
il = (qx.^2 + qy.^2 >= 0.01);
qx(il) = 0;
qy(il) = 0;
il = qx>0 && qy>0;
q = sum(exp(-((Dx-qx(il)).^2 + (Dy-qy(il)).^2)/4));
%// etc. for vectorization of the inner loops

Efficient solution to object detection algorithm

I'm trying to implement this paper 'Salient Object detection by composition' here is the link: http://research.microsoft.com/en-us/people/yichenw/iccv11_salientobjectdetection.pdf
I have implemented the algorithm but it takes a long time to execute and display the output. I'm using 4 for loops in the code(Using for loops is the only way I could think of to implement this algorithm.) I have searched online for MATLAB code, but couldn't find anything. So can anyone please suggest any faster way to implement the algorithm. Also in the paper they(the authors) say that they have implemented the code using MATLAB and it runs quickly. So there definitely is a way to write the code more efficiently.
I appreciate any hint or code to execute this algorithm efficiently.
clc
clear all
close all
%%instructions to run segment.cpp
%to run this code
%we need an output image
%segment sigma K min input output
%sigma: used for gaussian smoothing of the image
%K: scale of observation; larger K means larger components in segmentation
%min: minimum component size enforced by post processing
%%
%calculating composition cost for each segment
I_org = imread('segment\1.ppm');
I = imread('segment\output1.ppm');
[rows,cols,dims] = size(I);
pixels = zeros(rows*cols,dims);
red_channel = I(:,:,1);
green_channel = I(:,:,2);
blue_channel = I(:,:,3);
[unique_pixels,count_pixels] = countPixels(I);
no_segments = size(count_pixels,1);
area_segments = count_pixels ./ (rows * cols);
appearance_distance = zeros(no_segments,no_segments);
spatial_distance = zeros(no_segments,no_segments);
thresh = multithresh(I_org,11);
thresh_values = [0 thresh];
for i = 1:no_segments
leave_pixel = unique_pixels(i,:);
mask_image = ((I(:,:,1) == leave_pixel(1)) & (I(:,:,2) == leave_pixel(2)) & (I(:,:,3) == leave_pixel(3)));
I_i(:,:,1) = I_org(:,:,1) .* uint8((mask_image));
I_i(:,:,2) = I_org(:,:,2) .* uint8((mask_image));
I_i(:,:,3) = I_org(:,:,3) .* uint8((mask_image));
LAB_trans = makecform('srgb2lab');
I_i_LAB = applycform(I_i,LAB_trans);
L_i_LAB = imhist(I_i_LAB(:,:,1));
A_i_LAB = imhist(I_i_LAB(:,:,2));
B_i_LAB = imhist(I_i_LAB(:,:,3));
for j = i:no_segments
leave_pixel = unique_pixels(j,:);
mask_image = ((I(:,:,1) == leave_pixel(1)) & (I(:,:,2) == leave_pixel(2)) & (I(:,:,3) == leave_pixel(3)));
I_j(:,:,1) = I_org(:,:,1) .* uint8((mask_image));
I_j(:,:,2) = I_org(:,:,2) .* uint8((mask_image));
I_j(:,:,3) = I_org(:,:,3) .* uint8((mask_image));
I_j_LAB = applycform(I_j,LAB_trans);
L_j_LAB = imhist(I_j_LAB(:,:,1));
A_j_LAB = imhist(I_j_LAB(:,:,2));
B_j_LAB = imhist(I_j_LAB(:,:,3));
appearance_distance(i,j) = sum(min(L_i_LAB,L_j_LAB) + min(A_i_LAB,A_j_LAB) + min(B_i_LAB,B_j_LAB));
spatial_distance(i,j) = ModHausdorffDist(I_i,I_j) / max(rows,cols);
end
end
spatial_distance = spatial_distance ./ max(max(spatial_distance));
max_apperance_distance = max(max(appearance_distance));
composition_cost = ((1 - spatial_distance) .* appearance_distance) + (spatial_distance * max_apperance_distance);
%%
%input parameters for computation
window_size = 9; %rows and colums are considered to be same
window = ones(window_size);
additional_elements = (window_size - 1)/2;
I_temp(:,:,1) = [zeros(additional_elements,cols);I(:,:,1);zeros(additional_elements,cols)];
I_new(:,:,1) = [zeros(rows + (window_size - 1),additional_elements) I_temp(:,:,1) zeros(rows + (window_size - 1),additional_elements)];
I_temp(:,:,2) = [zeros(additional_elements,cols);I(:,:,2);zeros(additional_elements,cols)];
I_new(:,:,2) = [zeros(rows + (window_size - 1),additional_elements) I_temp(:,:,2) zeros(rows + (window_size - 1),additional_elements)];
I_temp(:,:,3) = [zeros(additional_elements,cols);I(:,:,3);zeros(additional_elements,cols)];
I_new(:,:,3) = [zeros(rows + (window_size - 1),additional_elements) I_temp(:,:,3) zeros(rows + (window_size - 1),additional_elements)];
cost = zeros(rows,cols);
for i = additional_elements + 1:rows
for j = additional_elements+1:cols
I_windowed(:,:,1) = I_new(i-additional_elements:i+additional_elements,i-additional_elements:i+additional_elements,1);
I_windowed(:,:,2) = I_new(i-additional_elements:i+additional_elements,i-additional_elements:i+additional_elements,2);
I_windowed(:,:,3) = I_new(i-additional_elements:i+additional_elements,i-additional_elements:i+additional_elements,3);
[unique_pixels_w,count_pixels_w] = countPixels(I_windowed);
unique_pixels_w = setdiff(unique_pixels_w,[0 0 0],'rows');
inside_segment = setdiff(unique_pixels,unique_pixels_w);
outside_segments = setdiff(unique_pixels,inside_segment);
area_segment = count_pixels_w;
for k = 1:size(inside_pixels,1)
current_segment = inside_segment(k,:);
cost_curr_seg = sort(composition_cost(ismember(unique_pixels,current_segment,'rows'),:));
for l = 1:size(cost_curr_seg,2)
if(ismember(unique_pixels(l,:),outside_segments,'rows') && count_pixels(l) > 0)
composed_area = min(area_segment(k),count_pixels(l));
cost(i,j) = cost(i,j) + cost_curr_seg(l) * composed_area;
area_segment(k) = area_segment(k) - composed_area;
count_pixels(l) = count_pixels(l) - composed_area;
if area_segment(k) == 0
break
end
end
end
if area(k) > 0
cost(i,j) = cost(i,j) + max_apperance_distance * area_segment(k);
end
end
end
end
cost = cost / window_size;
The code for the countPixels function:
function [unique_rows,counts] = countPixels(I)
[rows,cols,dims] = size(I);
pixels_I = zeros(rows*cols,dims);
count = 1;
for i = 1:rows
for j = 1:cols
pixels_I(count,:) = reshape(I(i,j,:),[1,3]);
count = count + 1;
end
end
[unique_rows,~,ind] = unique(pixels_I,'rows');
counts = histc(ind,unique(ind));
end

Why do I get such a bad loss in my implementation of k-Nearest Neighbor?

I'm trying to implement k-NN in matlab. I have a matrix of 214 x's that have 9 columns of attributes with the 10th column being the label. I want to measure loss with a 0-1 function on 10 cross-validation tests. I have the following code:
function q3(file)
data = knnfile(file);
loss(data(:,1:9),'KFold',data(:,10))
losses = zeros(25,3);
new_data = data;
new_data(:,10) = [];
sdd = std(new_data);
meand = mean(new_data);
for s = 1:214
for q = 1:9
new_data(s,q) = (new_data(s,q) - meand(q)) / sdd(q);
end
end
new_data = [new_data data(:,10)];
for k = 1:25
loss1 = 0;
loss2 = 0;
for j = 0:9
index = floor(214/10)*j+1;
curd1 = data([1:index-1,index+21:end],:);
curd2 = new_data([1:index-1,index+21:end],:);
for l = 0:20
c1 = knn(curd1,k,data(index+l,:));
c2 = knn(curd2,k,new_data(index+l,:));
loss1 = loss1 + (c1 ~= data(index+l,10));
loss2 = loss2 + (c2 ~= new_data(index+l,10));
end
end
losses(k,1) = k;
losses(k,2) = 100*loss1/210;
losses(k,3) = 100*loss2/210;
end
function cluster = knn(Data,k,x)
distances = zeros(193,2);
for i = 1:size(Data,1)
row = Data(i,:);
d = norm(row(1:size(row,2)-1) - x(1:size(x,2)-1));
distances(i,:) = [d row(10)];
end
distances = sortrows(distances,1);
cluster = mode(distances(1:k,2));
I'm getting 40%+ loss with almost no correlation to k and I'm sure that something here is wrong but I'm not quite sure.
Any help would be appreciated!

Filter points using hist in matlab

I have a vector. I want to remove outliers. I got bin and no of values in that bin. I want to remove all points based on the number of elements in each bin.
Data:
d1 =[
360.471912914169
505.084636471948
514.39429429184
505.285068055647
536.321181755858
503.025854206322
534.304229816684
393.387035881967
396.497969729985
520.592172434431
421.284713703215
420.401106087984
537.05330275495
396.715779872694
514.39429429184
404.442344469518
476.846474245118
599.020867750031
429.163139144079
514.941744277933
445.426761656729
531.013596812737
374.977332648255
364.660115724218
538.306752697753
519.042387479096
1412.54699036882
405.571202133485
516.606049132218
2289.49623498271
378.228766753667
504.730621222846
358.715764917016
462.339366699398
512.429858614816
394.778786157514
366
498.760463549388
366.552861126468
355.37022947906
358.308526273099
376.745272034036
366.934599077274
536.0901883079
483.01740134285
508.975480745389
365.629593988233
536.368800360349
557.024236456548
366.776498701866
501.007025898839
330.686029339009
508.395475983019
429.563732174866
2224.68806802212
534.655786464525
518.711297351426
534.304229816684
514.941744277933
420.32368479542
367.129404978681
525.626188464768
388.329756778952
1251.30895065927
525.626188464768
412.313764019587
513.697381733643
506.675438520558
1517.71183364959
550.276294237722
543.359917550053
500.639590923451
395.129864728041];
Histogram computation:
[nelements,centers] = hist(d1);
nelements=55 13 0 0 1 1 1 0 0 2
I want to remove all points apearing less than 5 (in nelements). It means only first 2 elements in nelements( 55, 13 ) remains.
Is there any function in matlab.
You can do it along these lines:
threshold = 5;
bin_halfwidth = (centers(2)-centers(1))/2;
keep = ~any(abs(bsxfun(#minus, d1, centers(nelements<threshold))) < bin_halfwidth , 2);
d1_keep = d1(keep);
Does this do what you want?
binwidth = centers(2)-centers(1);
centersOfRemainingBins = centers(nelements>5);
remainingvals = false(length(d1),1);
for ii = 1:length(centersOfRemainingBins )
remainingvals = remainingvals | (d1>centersOfRemainingBins (ii)-binwidth/2 & d1<centersOfRemainingBins (ii)+binwidth/2);
end
d_out = d1(remainingvals);
I don't know Matlab function for this problem, but I think, that function with follow code is what are you looking for:
sizeData = size(data);
function filter_hist = filter_hist(data, binCountRemove)
if or(max(sizeData) == 0, binCountRemove < 1)
disp('Error input!');
filter_hist = [];
return;
end
[n, c] = hist(data);
sizeN = size(n);
intervalSize = c(2) - c(1);
if sizeData(1) > sizeData(2)
temp = transpose(data);
else
temp = data;
end
for i = 1:1:max(sizeN)
if n(i) < binCountRemove
a = c(i) - intervalSize / 2;
b = c(i) + intervalSize / 2;
sizeTemp = size(temp);
removeInds = [];
k = 0;
for j = 1:1:max(sizeTemp)
if and(temp(j) > a, less_equal(temp(j), b) == 1)
k = k + 1;
removeInds(k) = j;
end
end
temp(removeInds) = [];
end
end
filter_hist = transpose(temp);
%Determines when 'a' less or equal to 'b' by accuracy
function less_equal = less_equal(a, b)
delta = 10^-6; %Accuracy
if a < b
less_equal = 1;
return;
end
if abs(b - a) < delta
less_equal = 1;
return;
end
less_equal = 0;
You can do something like this
nelements=nelements((nelements >5))