For GSOC, I am about to read through the julia language and master it’s high performance and parallel computing features.

There is a good article talking about julia Why am I Betting on Julia.

As a language designed for science computing.

What we care is

  1. making it work.
  2. making it fast.

I have divided this article into five sections recording the notes I write during the learning path.

  1. Julia Documents
  2. Book - Mastering Julia
  3. Book - High Performance Julia
  4. Book - Mastering Julia
  5. Book - Quant Julia

Resources I used

Websites

juliaopt: julia数值优化
julia doc :官方文档
julia 数值课 : 18.330 CS
forio tutorial : forio tutorial
julia blog
quant-julia
quant-julia online
julia&kaggle

Books

Julia high performance
Mastering julia
julia-quant
Julia for data science

Introduction

Julia is a high-performance dynamic programming language for scientific and technical computing. It combines the simplicity of Python with a more sophisticated compiler and many small improvements that make the platform easier to use and better suited for numerical computation.

Most importantly, Julia is a lot of fun!
To get started, I recommend JuliaBox for easy access to Julia from your browser.
If you are already familiar with MATLAB or Python, you can have a quick look at the “Basics”, “Interactive Widgets” and “Multiple Dispatch” tutorials that come with JuliaBox. If you care about interfacing native code, look at “Calling C and Python”.

If you are familiar with any programming language, this tutorial will get you up to speed quickly.

At this point, depending on your prior experience, you either already feel comfortable with how things are working, or you will have to work through Learning Julia the Hard Way. A more lightweight approach is Julia By Example. And then, there is always the reference manual.

Setup

julia貌似不能再cmd里面打开
直接输入julia 显示没有找到命令行
在cmd输入下面, symlink 到bin里

n -s /Applications/Julia-0.4.5.app/Contents/Resources/julia/bin/julia /usr/local/bin/julia

OK

上面还是有点问题, 貌似内置自动安装的时候就会在命令行可以运行,. 我又重新安装了一遍…
无语啊, 老是在安装库的时候一直卡住 也不知道什么情况,,, 无语了 …..
搞了老久 说来还有好多作业没写呢…

最后终于弄好了, 因为老是在最后一步弹出homebrew error 所以去查了一下, 貌似是我电脑的git 版本太低, 然后用homebrew把GIT更新了一下, 在HOMEBREW LINK GIT连接后, 又是not writable,…这里在次修改一下权限sudo chown -R memoiry rep

进入julia, using Gadfly 终于好了….

设置atom (用了一会决定还是用sublime吧..)

经过选择最终还是觉得atom这个IDE还是听不错的, 在配合HYDROGEN这个PACKAGES可以达到MMA的效果

但是不知道怎么在我电脑直接安装不了..只能手动安装了

cd ~/.atom/packages
git clone https://github.com/JuliaLang/atom-language-julia
cd atom-language-julia
npm install

OK

这里是安装JULIA的语言配置,

下面安装HYDROGEN 手动安装过程类似, 就不复述了

进入HYDROGEN RUN

输入

TEST

1. Julia Documents

控制流

if elseif end
while
try catch x isa
try finally

使用@sprintf进行格式化字符串输入

Symbol类型 :asdasd
Dict{Int, Symbol}(3 => :asd )

函数内部也可以定义函数 函数可以返回函数, 可以用这种方法进行函数构造, 进一步进行函数抽象.

函数

multi dispatch
就是一个函数可以由多种方法, 其调用与传入参数的类型有关.
这种方式有利于抽象!

Number类型, Any类型都是可以的
::来定义类型,
:来定义状态符号
methods()查看定义
当没有::, 自动用Any代替

Although it seems a simple concept, multiple dispatch on the types of values is perhaps the single most powerful and central feature of the Julia language. Core operations typically have dozens of methods:
这里说multi dispatch是julia最强大的功能了..
可以试一下methods(+)
julia中一切都是表达式
注意要避免定义的模糊性

函数可以由类型变量

same_type{T}(x::T, y::T) = true;
same_type(x,y) = false;

这点可以用来捕捉类型, {T}用来定义类型.
类型参数用{}来包含
{}[]注意两种不同的东西
可以用append!
push!
[[1 2 3]…]中的…可以当做flatten操作

myappend{T}(v::Vector{T}, x::T) = [v..., x]
mytypeof{T}(x::T) = T

same_type_numeric{T<:Number}(x::T, y::T) = true
same_type_numeric(x::Number, y::Number) = false

这里可以对类型参数进行限制, 不用:: 用<:, 这里<:相当于小与后面的类型

类型

isa()
typeof()
super()
Val类型
Val{true}
Val{false}
isnull() Nullable对象

abstract 抽象类型, 只是用来 <:
对于multidispatch 善于利用抽象类型

fieldname()

组合类型 Union{lists}

immutable rational{T <: Integer} <: Real
num :: T
den :: T
end

typealias 一般作为union使用

元组的定义是immutable, 注意

  1. 元组参数任意个
  2. 元祖Tuple{Integer} <: Tuple{Real}, 这点需要注意
  3. 元祖没有成员名字, 只能通过index来查找.

还有
Array{Float64,1} <: Array{Float64} <: Array

typealias Vector{T} Array{T,1}
typealias Matrix{T} Array{T,2}

参数类型, 相当于parametric types, C++中的vector{}. (泛型编程)

注意类型参数的使用, 可以用来

  1. 限制两参数类型相同
  2. 限制某参数类型在某个类型的子类型里.

same_type_numeric{T<:Number}(x::T, y::T) = true
same_type_numeric(x::Number, y::Number) = false

关于可选参数

f(a=1,b=2) = a+2b

相当于

f(a,b) = a+2b
f(a) = f(a,2)
f() = f(1,2)

Since Point{Float64} is not a subtype of Point{Real}, the following method can’t be applied to arguments of type Point{Float64}:

function norm(p::Point{Real})
   sqrt(p.x^2 + p.y^2)
end

The correct way to define a method that accepts all arguments of type Point{T} where T is a subtype of Real is:

function norm{T<:Real}(p::Point{T})
   sqrt(p.x^2 + p.y^2)
end
111


多态
The ability to write code that can operate on different types is called polymorphism. 


immutabletype的区别

一般考虑使用哪种, 考虑如果成员值相同时两个实例是否相同, 如果相同, 那么考虑使用immutable

1. immutable的传递是copy()传递(如数), type的传递是引用传递(如Array)
2. 不可变类型的成员不能改变

一般考虑效率使用immutable, 把一定会变的数据放在另外的type.


### 构造器

用来创造复合类型的实例, 相当于一个函数.
类型目标本身也可以是构造器, 可以创造自己的实例

```julia
type Foo
  bar
  baz
end

foo = Foo(1,2)

foo.bar

foo.baz

定义类型后, 可以看做构造函数, 输入参数后, 当做对象使用

可以用immutable, 这里是不可变的

默认类型构造器内部有构造函数,不用再加new这个样子

type T1
  x::Int64
end

type T2
  x::Int64
  T2(x) = new(x)
end
type SelfReferential
  obj::SelfReferential

  SelfReferential() = (x = new(); x.obj = x)
end

这里可以引入一个初始化操作
递归调用

参数构造器

type Point{T<:Real}
         x::T
         y::T
       end
Point{Int64}(1,2)

后面一种为显示的构造类型, 直接给出int64

immutable Rational{T<:Integer} <: Real
    num::T
    den::T

    function Rational(num::T, den::T)
        if num == 0 && den == 0
            error("invalid rational: 0//0")
        end
        g = gcd(den, num)
        num = div(num, g)
        den = div(den, g)
        new(num, den)
    end
end
Rational{T<:Integer}(n::T, d::T) = Rational{T}(n,d)
Rational(n::Integer, d::Integer) = Rational(promote(n,d)...)
Rational(n::Integer) = Rational(n,one(n))

//(n::Integer, d::Integer) = Rational(n,d)
//(x::Rational, y::Integer) = x.num // (x.den*y)
//(x::Integer, y::Rational) = (x*y.den) // y.num
//(x::Complex, y::Real) = complex(real(x)//y, imag(x)//y)
//(x::Real, y::Complex) = x*y'//real(y*y')

function //(x::Complex, y::Complex)
    xy = x*y'
    yy = real(y*y')
    complex(real(xy)//yy, imag(xy)//yy)
end

此为Rational类型的定义
在内部定义函数进行异常处理

new()进行类型的构造, 给出参数就可以了

似乎只是用来构造类型, 内部保存的数据, 但是该类型不能进一步调用方法.

模块

模块作为一个项目的顶层文件, 定义引入的东西和引出的东西

包含

module MyModule
using Lib

using BigLib: thing1, thing2

import Base.show

importall OtherLib

export MyType, foo

type MyType
    x
end

bar(x) = 2x
foo(a::MyType) = bar(a.x) + 1

show(io, a::MyType) = print(io, "MyType $(a.x)")
end

标准库有
Core, Main, Base

push!(LOAD_PATH, “”)

多维数组

最基础的数组类型是AbstractArray{T,N}
其中N是维数, 一般说一纬是列向量, 行向量是二维的.
T是类型.

一般的, julia不需要向量操作来进行加速, 自带类型推断和代码优化.

一般的 数组操作不影响实际数组, 加上!才代表影响, 这点要注意

Note that there is a difference between min() and max(), which operate elementwise over multiple array arguments, and minimum() and maximum(), which find the smallest and largest values within an array.

注意julia中的min max是用来比较的, 单个array要用minimum. maximum
@vectorize_1arg() and @vectorize_2arg()
用来对一个函数进行向量化

如 @vectorize_1arg Number square

似乎没有啥用?

repmat进行数组重复
替代的做法是使用broadcast进行传播
broadcast(+, a, A)

tuple作为元组, 如(2,1,3)比array更加纯粹

stride获得间隔

subArray对Array进行索引后得到的类型

对于稀疏矩阵

CSC存储形式, 类型为SparseMatrixCSC{Tv,Ti}

type SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrix{Tv,Ti}
    m::Int                  # Number of rows
    n::Int                  # Number of columns
    colptr::Vector{Ti}      # Column i is in colptr[i]:(colptr[i+1]-1)
    rowval::Vector{Ti}      # Row values of nonzeros
    nzval::Vector{Tv}       # Nonzero values
end

这里可以看到<:可以看为对一种类型的继承

稀疏矩阵构造器

sp前缀,
后面都和普通矩阵构造一样

spzeros(100,100) #这里spzeros(dims)注意dims完全一致
a = speye(1000,1000);
a[100,100]

更加一般的,
使用sparse()函数
sparse(I,J,V), 其中I为row index, J是column index, V是value
反函数是findn()找到索引, 找到值findnz()

也可以使用sparse(A)对一个矩阵进行稀疏化
反过来使用full转化为dense matrix

注意fill函数的使用!

网络与流

最基本的I/O操作

read() write()

write(STDOUT, “hello, world!”)
read(“.file”, “w)
readbytes()
readline()
两个用处不同, 前者用来单个读取成数组, 后者直接变成了一个字符串

for line in eachline(STDIN)
    print("Found $line")
end
while !eof(STDIN)
    x = read(STDIN, Char)
    println("Found: $x")
end

两种方法都可以用来循环读取

Opening a file, doing something to its contents, and closing it again is a very common pattern. To make this easier, there exists another invocation of open() which takes a function as its first argument and filename as its second, opens the file, calls the function with the file as an argument, and then closes it again. For example, given a function:

使用open(xxx) do f

end
进行文件读写, 不用写close(f)

并行计算

julia中的并行计算基于 remote call and remote references

一个remote call有处理器发起, 返回一个remote references

julia -p n
其中n为几个处理器并行处理
比如我的电脑有2个CPU核, 就可以设置
julia -p 2

使用函数
remotecall(2,func)
返回一个ref,
使用fetch得到结果
使用s = @spawnat 2 xxx
得到一个新的ref
fetch得到结果
两个一起, 可以remotecall_fetch()

一般来说 我们需要把一个过程写成函数形式
然后用@spawn 进行并行化
spawn进行处理器分配, 然后fetch() + fetch()

一点典型的使用

require("count_heads")

a = @spawn count_heads(100000000)
b = @spawn count_heads(100000000)
fetch(a)+fetch(b)

这里require来对外部的函数进行调用
然后并行分配, 最后fetch

更一般的 使用@parallel

nheads = @parallel (+) for i=1:200000000
  int(randbool())
end

这个是并行for, 并行for内部的操作必须与i无关, i只关于次数

@parallel (+){这里相当于一个reduce操作} for i = 1:10000
操作(相当于结果在这里)
end

rand的使用非常方便, 另外一种调用就是直接rand(1:100)可以从这个整数范围内进行选数, rand(1,120,30)是维数限定.

数组index内部直接可以用end代替长度
如a[rand(1:end)]也是可以的

pmap(func,M)
并行map
注意julia中向量化反而会变慢, 因为是类C的代码

字典 Dict{xx,xx} Vector{xx,xx} Array{xx,xx}

首先定义一个空字典, 注意julia中的复合类型只是复合而已, 相当于一个数据的集合, 不包含action, 这与面向对象的是不同的, 相反的, 使用multi dispatch进行多操作.

module Auth 
type UserCreds
      uid::Int
      password::ASCIIString
     fullname::ASCIIString
     email::ASCIIString
     admin::Bool
end 

function matchPwds(_mc::Dict{ASCIIString,UserCreds}, _
   name::ASCIIString, _pwd::ASCIIString)
    return (_mc[_name].password == base64(_pwd) ? true : false)
   end
   isAdmin(_mc::Dict{ASCIIString,UserCreds},_name::ASCIIString) = _mc[_name].admin;exportUserCreds, matchPwds, isAdmin;
end


using Auth
AA = Dict{ASCIIString,UserCreds}();
AA["malcolm"] =  UserCreds(101,base64("Pa55word"),"Malcolm
Sherrington","malcolm@myemail.org",true);
println(matchPwds(AA, "malcolm", "Pa55word") ? "OK" : "No, sorry")

新建数组, []
新建字典, Dict()
对字典进行遍历, 可以使用for kk in keys(xx)
集合 Set()
setdiff()

一般对stack使用pop push, 对队列使用push, unshift

DataStructures库包含了一些常用的库, 比如
栈, 队列, 堆, 排序表, 链表, 数字树等

deque是双边队列

队列可以使用enqueue!(), dequeue!()

2. Book - Mastering Julia

Features

首先是julia的一些特性
其优点有

  1. 并行处理
  2. multi dispatch

  3. 主要是计算速度快, 能比肩C, 这一点要注意利用

Pkg.add
Pkg.rm
Pkg.update
Pkg.clone

数据类型

Int
Float
BigInt
Uint
Bool true false 注意在julia中只有布尔能代表布尔, 其能代表整型数, 但不是不能反过来
列表解析式
Array(type,个数)用来初始化数组, 内部的值不确定, 不能像matlab一样动态增加, julia是强类型的, 但是带有类型推导系统而已.
也有matlab的函数
zeros, ones, rand, eye 但是注意生成的时候维数和给定的一样, 不像matlab一样会生成方阵

@printf宏
直接索引的时候按照列进行索引, 这个和matlab一样, 具体在数学上表现为vec(M)
reshape函数
transpose函数, 或者直接用’

  • \
    .*

string

char
‘\u0041’
julia中的字符是不可变的
注意不能用[:14],这里吧:14认作定义符号了
使用 *符号相连两字符串
使用endof函数进行遍历
字符串的length不代表总长, 直到最后一个空格

正则表达式

用r””表示正则表达式

empat = r"^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z] 
{2,4})$" 
ismatch(empat, "fred.flintstone@bedrock.net")

ismatch
match
可以给出match的信息
包括.match .offset

unique函数

STDIN输入
eof(STDIN)
else
chomp(readline(STDIN))

all(func,s)
map(func,s)

intersect

实数, 有理数, 复数

im
Big()
Real
内置函数
log
exp
sin
cos
gamma
bessel
zeta
hankel

特殊数
Inf
NaN
注意Float64没有上下限, 可以从typemin max看出来

有理数
\
3\2
num(x)
den(x)
float(x)

abs
angle

5. julia-quant

字符串

strip
split
match

for line in eachline(f)
a1, a2 = split(line,”:”)
a1 = parse(Float, a1)
end

常用的library

  1. Distributions

  2. DataFrames
    优点是能处理NA
    DataArray @data([12 23 4 NA])
    DataFrame
    [:name]尽心索引, 不用 String
    describe()

readtable(“data_file.csv”)
writetable(“data_file.csv”, df)
还有两个包是juliaStats, juliaQuant

  1. Interpolation

网格数据

itp_const = scale(interpolate(y, BSpline(Constant()), OnGrid()), x)
itp_linear = scale(interpolate(y, BSpline(Linear()), OnGrid()), x)
itp_cubic = scale(interpolate(y, BSpline(Cubic(Line())), OnGrid()), x)

非网格数据

itp_const = interpolate((x, ), y, Gridded(Constant()))
itp_linear = interpolate((x, ), y, Gridded(Linear()))

6. Function Notes

trivial examples

DataFrame操作

using DataFrames
# Lets make up some data
df=DataFrame(A=rand(5),B=["8", "9 meters", "4.5", "3m", "12.0"])

# And then make a function to clean the data
function fixdata(arr)
    result = DataArray(Float64, length(arr))
    reg = r"[0-9]+\.*[0-9]*"
    for i = 1:length(arr)
        m = match(reg, arr[i])
        if m == nothing
            result[i] = NA
        else
            result[i] = float64(m.match)
        end
    end
    result
end

# Then just apply the function to the column to clean the data
# and then replace the column with the cleaned data.
df[:B] = fixdata(df[:B])

function notes

combinations 选取几个排列
permutations 全排列
std
mean
middle
prod
sum
findmax
maximum
max
minimum
min
findfirst
find(case,array)
count
any
all
filter
union
intersect
length
size
ndims
countnz

collect to convert iterable array

push!后插
unshift!前插

pop!
shift!

deleteat!

resize!
append!
prepend!
rot90()
empty!()

similar() 复制数组/ 注意数组在函数里面是指针 会被改变

reshape()
ones()
zeros()
diagm()

hcat()水平
vcat()垂直

inv
pinv
transpose
rank秩
nullspace
trace diag迹

norm: The Euclidean norm, ||x|| — = sqrt(x1^2 + x2^2 + … xn^2), is found by norm(x):

The Euclidean distance between vectors x and y — ||x - y|| — is found by norm(x - y):

The angle between two vectors a and b is arccos(aTb)/(||a|| ||b||):

内积 dot

norm(X,2) 多阶 默认是2

cos
acos
sin
asin

norm(B, Inf) 无穷范数 就是向量的最大值

randperm(10)
sort()
sort!()
sortperm() 索引

r[sortperm(r)]

sort(a, by = x -> parse(x))

parse 相当于 python的eval

匿名函数 x -> parse(x)

enumerate(x) 枚举

for i in enumerate

split()用空格分割, 与python类似

sort(x, lt = x -> xxx > xxx)
less than 这里相当于比较前后两者关系

有 lt 与 by

end 关键词 可以用来索引

$x 在println中使用

arguments

args..直接作为参数列表
不需要列出很多参数了

for arg in args

这里用end做控制
不用:

map
filter
count
前面函数, 后面数据

f([3,4]) ERROR: f has no method matching f(::Array{Int64,1})

用这种方法可以传递列表参数进去
[3,4]…

map(//, [5:24], fill(32,20))

对多参数函数, 可以这样

reduce

相当于积累进行函数变换

eg:
reduce(+, 1:10)

所以reduce传入的函数必须要有有两个参数

这里单一函数声明可以

f(a,b) = a+b

l(a, b) = length(a) > length(b) ? a : b

三目运算符
julia也有
reduce(l, split(“This is a sentence containing some very long strings”))

这样就可以算出字符串列表中长度最长的

最好使用匿名函数 匿名函数里面可以使用; 来多表达式

类似的有fold
foldl, foldr
相当于可以控制左右方向的reduce

Julia offers other functions in this group: check out mapreduce(), mapfoldl(), and mapfoldr().

匿名函数可以0参数 () -> rand(0:10)

::Real ::Int 显示声明参数类型

applicable 用来测试函数是否可行
这里的可行一般是指参数类型是否正确

endswith 检查字符串
startswith 同样的

methods 找出函数内一共用了哪些函数

e pi 是内置值

使用reduce(vcat, data)对Array{Any,2}进行数值化

NA nothing

@data([])

可以传入函数

使用block进行更多的操作

opne(xx,’w’) do f

end

map([1,2,3]) do x

end

函数的使用

…用来分解多参数 与 ;用来给关键词输入(选择输入)

可选和关键词输入(…, ;)

;进行分解后的参数相当于多余参数, 不影响顺序参数的输入, 即使插在顺序输入的中间

正常是顺序输入

多输出 可以 x,y 返回一个tuple

a1,a2 = ss(x)

a = 1_000_000 数位分隔符

@time 相当于 tic;exp();toc;

@which 可以看出对于一个具体的调用, 重载的是哪一个函数.(debug使用, 观察是不是调用错误)

@printf 进行格式化输出

julia> @printf("Hello World!")
Hello World!

julia> A = [1 2 3;4 5 6]
2x3 Array{Int64,2}:
1  2  3
4  5  6

julia> @printf("A has %d elements.",length(a))
A has 6 elements.

julia> @printf("sqrtm(2) is %4.2f.",sqrtm(2))
sqrtm(2) is 1.41.

@sprintf 格式化字符串赋值

@assert 与C语言的assert相似, 表达式为真, 则什么都不做, 为假返回错误.

不过一般测试不用@assert, 使用@test宏,

使用前 using Base.Test

iseven
isodd

for i=1:3
end
会把外面定义的i改变
列表解析式不会.

randperm
sortperm

const
local
global

关于字典
a = Dict()
a[1] = xxx
haskey(a,xx)
get(a,key,0) -default to 0

for (key,value) in dic

end

using StatsBase

有一个countmap函数计算频数, 返回的是字典

@inline相当于带类型检测的alias, 避免了函数调用开销.

@inbounds消去数组bound检测, 一般在程序写好了, 确定没有错误的时候使用.

注意[1 2 3]与[1,2,3]的区别, 后者是Array{T, 1} 前者是Array{T, 2}

s, v = eigs(A, nev = 3)用来计算前n个奇异值

Symmetry用来强制数组对称(有时候有精度问题要求对称的时候这样做)
当然, 也可以(K+K’)/2, 平均对称法.

Distributions.jl的使用

如dis = Normal(sigma,mu)建立一个概率模型
pdf(dis, x)返回参数概率

MvNormal 多变量参数

Distributions.jl

FAQ

  1. 关于…
    在函数中
    数组穿进去后用…可以化为几个参数
    定义时用, 可以将多个参数化为数组输入

  2. 函数传入数组
    数组参数传入的时候是引用传递, 在函数内部修改时会改变原来的值

  3. 类型
    julia是强类型的语言, 要写出高性能的代码, 那么函数的类型比较稳定, 也就是说固定类型输入对应固定类型输出,这点在multi-dispatch中体现出来, 不能一种类型输入对应多种类型出书

  4. 注意浮点溢出
    计算得时候一定要注意数的上下线, typemax(), 否则溢出造成错误, 这点从速度优化的角度考虑

  5. 无垃圾回收
    可以使用gc(), 但是一般A=0

  6. 注意importall和using区别
    一般只用using, 防止函数名称冲突, using的带有命名空间

  7. nothing type
    没有null, 一般返回nothing, Void 类型下

  8. 注意作用
    在while for 内定义的编程属于while for 作用于之内, 结束后会消失.

高性能优化

调用C或Fortran加速

尽管Julia声称速度和C相提并论,但是并不是所有的情况下都能有C的性能。合理地使用像LAPACK,BLAS,MUMPS这类已经高度优化的函数库有助于提升运行速度。

循环

使用@imbounds加速循环, 牺牲数组的bounds check, 就是索引检验, 保证程序正确性下使用.(先测试成功, 最后@imbounds加速)

julia>  function f(x)
        N = div(length(x),3)
        r = 0.0
        for i = 1:N
            for j = 1:N
                for k = 1: N
                    r += x[i+2*j]+x[j+2*k]+x[k+2*i]
                end
            end
        end
        r
        end
f (generic function with 1 method)

julia>  function f1(x)
        N = div(length(x),3)
        r = 0.0
        for i = 1:N
            for j = 1:N
                for k = 1: N
                    @inbounds r += x[i+2*j]+x[j+2*k]+x[k+2*i]
                end
            end
        end
        r
        end
f1 (generic function with 1 method)

julia> a = rand(2000);

julia> @time f(a)
elapsed time: 0.528003738 seconds (211264 bytes allocated)
4.4966644948005027e8

julia> @time f1(a)
elapsed time: 0.307557441 seconds (64 bytes allocated)
4.4966644948005027e8

可并行, 使用@simd, 并且提前分配内存.

@inline

对于经常使用的较短的计算函数, 使用@inline定义加速

矩阵运算

使用A_mul_B!函数.

julia> A = rand(5000,5000); x = rand(5000); y = rand(5000);
julia> @time y = A*x;
elapsed time: 0.016998118 seconds (40168 bytes allocated)
julia> @time A_mul_B!(y,A,x);
elapsed time: 0.012711399 seconds (80 bytes allocated)

其他

提前声明函数参数类型

发行自己的库

Finalizing Your Julia Package: Documentation, Testing, Coverage, and Publishing

简单的说

using PkgDev
PkgDev.generate("PkgName","license")

Kaggle Example

用kaglle上的一个简单的ML问题来做一下julia的hello world

….坑先留着