Julia open source reading
Analyse julia package’s source code to learn coding tips. Below are some notes.
- Distances.jl
- lightML.jl
- lightOPT.jl
- Optim.jl
Distances.jl-simd
主要知识点是 @inline, @simd, @imbounds, typealias, type, <:
typealias UnionXX Union{xx,xx,xx}
这种用来表示一种类型的集合, 非常常用
当定义一个类型后, 即声明type xx end
创建的时候可以像函数一样使用
x1,x2,x3 = s
s = (x1,x2,x3)
这种方法的使用
这个库是对距离计算的一个优化包, 我看了他的实现后发现很巧妙, 用了@simd和@imbounds来并行优化, 这个技巧算是一种向量化加速的技巧,使用SIMD.
核心部分是
function evaluate(d::UnionMetrics, a::AbstractArray, b::AbstractArray)
if length(a) != length(b)
throw(DimensionMismatch("first array has length $(length(a)) which does not match the length of the second, $(length(b))."))
end
if length(a) == 0
return zero(result_type(d, a, b))
end
s = eval_start(d, a, b)
if size(a) == size(b)
@simd for I in eachindex(a, b)
@inbounds ai = a[I]
@inbounds bi = b[I]
s = eval_reduce(d, s, eval_op(d, ai, bi))
end
else
for (Ia, Ib) in zip(eachindex(a), eachindex(b))
@inbounds ai = a[Ia]
@inbounds bi = b[Ib]
s = eval_reduce(d, s, eval_op(d, ai, bi))
end
end
return eval_end(d, s)
end
这里
可以看到分为4个部分, eval_start(), eval_op(), eval_reduce(), eval_end(),这四个部分把原来的计算并行化了, reduce可以看做一个向右的fold, 使用eval_op()来进行并行化, @imbounds来声明并行部分, 还有一个技巧就是cosine dist余弦距离的实现
# Cosine dist
function eval_start{T<:Real}(::CosineDist, a::AbstractArray{T}, b::AbstractArray{T})
zero(T), zero(T), zero(T)
end
@inline eval_op(::CosineDist, ai, bi) = ai * bi, ai * ai, bi * bi
@inline function eval_reduce(::CosineDist, s1, s2)
a1, b1, c1 = s1
a2, b2, c2 = s2
return a1 + a2, b1 + b2, c1 + c2
end
function eval_end(::CosineDist, s)
ab, a2, b2 = s
max(1 - ab / (sqrt(a2) * sqrt(b2)), zero(eltype(ab)))
end
cosine_dist(a::AbstractArray, b::AbstractArray) = evaluate(CosineDist(), a, b)
可以看到这里fold迭代的是一个set, 利用这个技巧, 可以巧妙的进行计算中间数, 最后在eval_end()中计算.
lightML
这个是我自己写的机器学习框架
分成三个部分