I am trying to convert one of my MATLAB scripts to Julia. I can get it to the same speed but not faster at the moment.
I know where the bottlenecks are, filling my sparse matrix with new entries and zeroing this in a loop. Example below:
using LinearAlgebra
using SparseArrays
#Init vars for loop -------------->
N=300;
#Sparse Matrix (to be filled)
J = spzeros(N,N); #zeros
#Matrix of computed values
A=rand(N,N);
#Precomputed vectors
y=rand(N);
x=ones(N);
dx=zeros(N);
zers=zeros(N);
I=zeros(Int64, N)
S=copy(I);
I=convert(Array{Bool,1},I) #convert to bool
#From now on inside loop -------------->
#Values of y change...
#Compute a flag of parts to fill
S.= y.>0.5;
I.= (S.==false);
Indx=findall(I)
#Function I would like to speed up
@time WorkOnEntries(J,A,x,y,Indx)
function WorkOnEntries(J,A,x,y,Indx)
for i=eachindex(Indx)
local idxi=Indx[i];
cons=(((y[idxi]^2) +(x[idxi]^2))^0.5);
p=(x[idxi]/cons)-1.0;
q=(y[idxi]/cons)-1.0;
for j=eachindex(Indx)
local idxj=Indx[j];
J[idxi,idxj]=A[idxi,idxj]*q; #can use J (or A)[CartesianIndex(idxi,idxi)]
end
J[idxi,idxi] +=p; #can use J[CartesianIndex(idxi,idxi)]
end
end
It is the function (WorkOnEntries.jl) that takes the time. Is there a simple way to speed this up and remove the allocations?
Secondly I then pass the matrix ‘J’ into IterativeSolvers.gmres!, i.e.
#Then passed to gmres
restart=30;
using IterativeSolvers
@time IterativeSolvers.gmres!(dx,J,y,initially_zero=true,restart=restart,tol=1e-6);
If I compare the result to MATLAB (code at bottom of file) the solver is sometimes slower (esp for the close to dense matrices I have). Secondly, should the output vector of IterativeSolvers.gmres match MATLAB’s gmres?
N=300:
Julia: 0.013295
MATLAB: 0.116265
N=1000:
Julia: 0.424527
MATLAB: 0.274945
Is there a better way to do this?
MATLAB code I used for comparison:
close;clear all
%Init vars for loop -------------->
N=300;
%Sparse Matrix (to be filled)
J = zeros(N,N); %zeros
%Matrix of computed values
A=rand(N,N);
%Precomputed vectors
y=rand(N,1);
x=ones(N,1);
dx=zeros(N,1);
zers=zeros(N,1);
%From now on inside loop -------------->
%Values of y change...
%Compute a flag of parts to fill
S= y>0.5;
I = find(S==0);
p = (x(I)./((y(I).^2+x(I).^2).^0.5))-1;
q = (y(I)./((y(I).^2+x(I).^2).^0.5))-1;
J(I,I) = diag(kron(p,1)) + bsxfun(@times,(q),A(I,I));
J=sparse(J);
restart=30;
tic
[dx(I), ~] = gmres ( J(I,I), y(I),restart);
toc