In [1]:
using LinearAlgebra, Test
function f1(n::Int)
A=zeros(Int64, n,n);
for j=1:n ## Fortran Loop Style !!!!
for i=1:n
A[i,j] = i^j
end
end
return A
end
@elapsed f1(10^4)
Out[1]:
In [2]:
function f2(n::Int)
A = collect(1:n).^collect(1:n)'
return A
end
#@test f1(3) == f2(3)
@elapsed f2(10^4)
Out[2]:
In [3]:
a = [1,2]
b = a
a[1] = 4
b
Out[3]:
end and use brackets [,] for indexing
In [4]:
a = rand(2,2)
a[:, end] .= 1
a
Out[4]:
(1,n) and (m, n) → (m,n) and (m,n)
In [5]:
using Statistics
a=rand(3,3)
μ=mean(a, dims=1)
mean(a.-μ, dims=1)
Out[5]:
In [6]:
typeof(rand(3,1))
Out[6]:
In [7]:
typeof(rand(3))
Out[7]:
In [8]:
√Complex(-1)
Out[8]:
In [9]:
hilbert(n::Int) = reshape([ 1//(i+j-1) for i=1:n for j=1:n],n,n)
H₃=hilbert(3)
det(H₃)
Out[9]:
(x -> x*x)(2)map, reduce, filter functions
In [10]:
# seeking integers between squares and cubes
supSquares = filter(x->abs(√(x-1)-round(√(x-1))) < 1e-12, 1:100)
infCubes = filter(x->abs(∛(x+1)-round(∛(x+1))) < 1e-12, 1:100)
ξ = intersect(supSquares, infCubes)
Out[10]:
! convention like sort!
In [11]:
s=[4,1,3]; println("sort(s)=",sort(s));println("s=",s); sort!(s); println("s=",s)
In [12]:
e = :(2+2); println(typeof(e)); println(e.args); println(eval(e))
In [13]:
subtypes(Real)
Out[13]:
In [83]:
println("supertype of Real → ", supertype(Real))
println("supertype of Number → ",supertype(Number))
x<:y is the operator for the relation "x is a subtype of y"
In [14]:
Int64 <: Real
Out[14]:
Real) → cannot be instantiate
In [15]:
typeof(Real(1.2))
Out[15]:
some types are concrete (e.g. Int64) → they have not subtype except Union{}
In [16]:
subtypes(Int64)
Out[16]:
In [17]:
Union{}<:Int64
Out[17]:
In [85]:
struct zutos
x::Int
a::Array{Int64,1}
end
w = zutos(2, [1,2])
Out[85]:
In [86]:
w.x = 4
In [87]:
append!(w.a,3)'
Out[87]:
In [21]:
typeof((3,"haha"))
Out[21]:
In [22]:
Tuple{Int64,String} <: Tuple{Real,String}
Out[22]:
In [23]:
Real <: Union{String, Real}
Out[23]:
In [24]:
struct tableau{T<:Number}
n::Int64
a::Ptr{T}
end
a = tableau{Int64}(10, 0)
Out[24]:
☢ For efficiency, parametric types are invariants, except Tuples ☢
In [25]:
Array{Int64} <: Array{Real}
Out[25]:
In [26]:
@code_lowered 1+2.
Out[26]:
f
In [27]:
f(x::Float64,y::Float64) = 2x + y
f(x::Int,y::Int) = 2x + y
println(f(2.,3.));
println(f(2,3));
println(f(2,3.));
f
In [89]:
f(x::Real, y::Real) = 2x + y
f(2.0, 3)
Out[89]:
In [29]:
methods(f)
Out[29]:
In [30]:
using Distributed
addprocs(3)
nprocs()
Out[30]:
In [31]:
res1 = @spawnat 2 sum(rand(1000,1000).^2)
res2= @spawnat 3 sum(rand(1000,1000).^2)
fetch(res1)+fetch(res2)
Out[31]:
In [32]:
@everywhere function f3(n::Int)
res = @distributed (+) for i=1:n
sin(i*π/n)
end
return res
end
@time f3(200000000)
Out[32]:
In [33]:
function f4(n::Int)
res = 0
for i=1:n
res += sin(i*π/n)
end
return res
end
@time f4(200000000)
Out[33]:
pmap
In [34]:
@everywhere using Statistics
@everywhere function cost_mean(x)
s = zero(eltype(x))
for i = 1:100
s += mean(log(sin(exp(xi))) for xi in x)
end
return s
end
X = [rand(100_000) for j=1:20];
t1 = @elapsed map(cost_mean, X)
t2 = @elapsed pmap(cost_mean, X)
println("$t1, $t2")
In [35]:
using Base.Threads
println(Base.Threads.nthreads())
In [47]:
import Base.Threads.@spawn
# sort the elements of `v` in place, from indices `lo` to `hi` inclusive
function psort!(v, lo::Int=1, hi::Int=length(v))
if lo >= hi # 1 or 0 elements; nothing to do
return v
end
if hi - lo < 100000 # below some cutoff, run in serial
sort!(view(v, lo:hi), alg = MergeSort)
return v
end
mid = (lo+hi)>>>1 # find the midpoint
half = @spawn psort!(v, lo, mid) # task to sort the lower half; will run
psort!(v, mid+1, hi) # in parallel with the current call sorting
# the upper half
wait(half) # wait for the lower half to finish
temp = v[lo:mid] # workspace for merging
i, k, j = 1, lo, mid+1 # merge the two sorted sub-arrays
@inbounds while k < j <= hi
if v[j] < temp[i]
v[k] = v[j]
j += 1
else
v[k] = temp[i]
i += 1
end
k += 1
end
@inbounds while k < j
v[k] = temp[i]
k += 1
i += 1
end
return v
end
Out[47]:
In [48]:
a = rand(20000000);
b = copy(a); @time sort!(b, alg = MergeSort); # single-threaded
In [49]:
b = copy(a); @time sort!(b, alg = MergeSort);
In [50]:
b = copy(a); @time psort!(b); # two threads
In [51]:
b = copy(a); @time psort!(b);
In [38]:
using Base.Threads
f(x) = sin(x) + cos(x)
function serial(n)
s = 0.0
for x = 1:n
s += f(x)
end
return s
end
@elapsed serial(10^7)
Out[38]:
In [39]:
function threads(n)
res_vec = zeros(nthreads())
@threads for i ∈ 1:nthreads()
res_vec[i] = local_sum(threadid(), n, nthreads())
end
sum(res_vec)
end
function local_sum(id, n, nthread)
out = 0.0
l = 1 + div(n * (id-1), nthread)
u = div(n * id, nthread)
for x ∈ l:u
out += f(x)
end
out
end
@elapsed threads(10^7)
Out[39]:
In [52]:
io = open("skel.c","w")
write(io, "int ajoute2(int x) { return x+2; }")
close(io)
run(`gcc -o ajoute2.so --shared skel.c`);
w = ccall((:ajoute2, "./ajoute2.so"), Int32, (Int32,), 12)
run(`rm ajoute2.so skel.c`)
println("w = $w")
In [70]:
# example with matplotlib
using PyCall
using PyPlot
plt = pyimport("matplotlib.pyplot")
x = range(0;stop=2*pi,length=1000); y = sin.(3*x + 4*cos.(2*x));
plt.plot(x, y, color="red", linewidth=2.0, linestyle="--")
plt.show()
...
function simu(x::Array{Float64,1})
f = Ref{Float64}(0.)
c = cos.(1:n)[slice[1]:slice[2]]
df = zeros(slice[2]-slice[1]+1)
@assert size(c,1) == size(x, 1)
ccall((:compute_error, "./libpar_error.so"),
Cvoid, (Ref{Int32}, Ptr{Float64}, Ptr{Float64}, Ref{Float64}, Ptr{Float64}), size(x, 1), x, c, f, df)
return f[], df
end
function cost(x::Array{Float64,1})
f,G = simu(x)
return f
end
function grad(x::Array{Float64,1})
f,G = simu(x)
return G
end
function main()
MPI.Init()
comm = MPI.COMM_WORLD
nb_procs = MPI.Comm_size(comm)
rank = MPI.Comm_rank(comm)
global n, slice
n = parse(Int32, ARGS[1])
x = zeros(n)
slice = compute_slice(n, Int32(nb_procs), Int32(rank))
x[:] = 1:n
x_loc = x[slice[1]:slice[2]]
f,df = simu(x_loc)
res = optimize(cost, grad, x_loc, BFGS(); inplace =false)
x_min = Optim.minimizer(res)
x_glob = MPI.Gatherv(x_min, Cint[5,5], 0, comm)
if (rank == 0)
println(" |sol - cos(1:$n)| = ", norm(x_glob-cos.(1:n)))
end
MPI.Finalize()
end
...
module par_error
use mpi
use iso_c_binding, only: c_int32_t, c_double
public:: compute_error
contains
subroutine compute_error(n, x, c, f, df) bind(C, name="compute_error")
implicit none
integer(c_int32_t), intent(in) :: n ! size of the array
real(c_double), intent(in) :: x(n), c(n) !
real(c_double), intent(out) :: f
real(c_double), intent(out) :: df(n)
real(c_double) :: f_loc
integer(c_int32_t) :: code
f = 0.d0
! computing objective
f_loc = 0.5d0 * sum( (x - c)**2 )
call MPI_ALLREDUCE( f_loc, f, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD, code )
! computing gradient and ...
df = x - c
end subroutine compute_error
end module par_error
In [80]:
a = read(`env LD_PRELOAD="/home/fux/sources/nahasketa/julia/interfaces/fortran/withMPI/libpar_error.so" mpirun -np 2 julia /home/fux/sources/nahasketa/julia/interfaces/fortran/withMPI/test_optim.jl 10`, String)
Out[80]: