julia语言科学计算
Julia编程语言由Jeff Bezanson,Stefan Karpinski和Viral B Shah于2009年创建。 自2012年以来,它已广泛发布 ,此后,它的贡献者和用户社区不断壮大。 官方注册表中有700多个软件包,基本语言有400多个贡献者 。
Julia(Julia)旨在解决技术计算中普遍存在的“两种语言问题”。 在诸如Python,Matlab或R之类的高级动态语言中,交互式数据探索和算法原型设计非常方便且高效,但是扩展初始原型以处理更大的数据集很快会遇到这些环境中的性能限制。 12月的常规方法是依靠编译的C(或C ++或Fortran)扩展来优化对性能至关重要的计算。 对于在标准数组和数据帧上的常见操作,有成熟的扩展库-例如Python中的NumPy,SciPy,Pandas等。 但是,由于现有的库无法实现所需的全部功能,因此存在压力。 降级到较低级别的静态编译语言以提高性能会带来容易出错的问题,并且会导致工作效率降低,并且增加了对开发或编写新库的进入门槛。 现有语言中最近有一些项目可以帮助改善这种情况-Cython和Numba for Python,Matlab中改进的即时(JIT)编译,Rcpp for R等。 但是,在与现有生态系统相同的语言语义内进行操作的兼容性要求意味着,这些方法要么局限于该语言的易于优化的限制性子集,要么不适合日常交互使用。
Julia采取了另一种(“贪婪”)方法。 设计一种新的语言而不需要保持源(和二进制,以便编译后的扩展继续工作)与数十年前设计的语言的兼容性,这使我们能够结合现代技术,这些现代技术已经很好地确立了如何使动态语言表现良好。 通过类型推断和对标准库的精心设计以利用类型信息,可以对通用代码进行优化和积极的专业化。 Julia代码通过LLVM编译器框架通过JIT编译为本地指令,从而可移植到多个平台和体系结构。 多亏了LLVM ,Julia代码可以通过现代处理器上的SIMD指令利用硬件向量化。
作为一个简单的例子,我们可以看一下对偶数的基本实现。 这些是形式为“ a + bε”的数字,类似于复数,但不是“i²= -1”,而是由“ε²= 0”定义的对偶数字。 这是一个类似数字的类型,应该具有不可变的值语义,而不是可变的引用语义,因此我们使用“ immutable”关键字在Julia中定义它们。 值分量和epsilon分量应该是相同的数字类型,我们在Julia中用参数类型“ {T}”表示如下:
```
immutable DualNumber{T}
value::T
epsilon::T
end
```
为了在这种新类型上定义基本的算术运算,我们首先导入加法和乘法运算符,然后使用为“ DualNumber”类型定义的新方法对其进行扩展:
```
import Base: +, *
# one-liner function definition:
+(x::DualNumber, y::DualNumber) = DualNumber(x.value + y.value, x.epsilon + y.epsilon)
# longer form function definition:
function *(x::DualNumber, y::DualNumber)
return DualNumber(x.value * y.value, x.value * y.epsilon + y.value * x.epsilon)
end
```
我们可以通过LLVM对Julia编译的各个阶段进行内省,以优化本机代码以适应不同的专业需求。
`DualNumber`, such as `DualNumber{Int64}` and `DualNumber{Float64}`, using the `@code_llvm` and `@code_native` macros:
```
julia> x_i64 = DualNumber(1, 2)
DualNumber{Int64}(1,2)
julia> y_i64 = DualNumber(3, 4)
DualNumber{Int64}(3,4)
julia> @code_llvm x_i64 * y_i64
define void @"julia_*_21313"(%DualNumber* sret, %DualNumber*, %DualNumber*) {
top:
%3 = load %DualNumber* %1, align 8
%4 = extractvalue %DualNumber %3, 0
%5 = extractvalue %DualNumber %3, 1
%6 = load %DualNumber* %2, align 8
%7 = extractvalue %DualNumber %6, 0
%8 = extractvalue %DualNumber %6, 1
%9 = mul i64 %7, %4
%10 = insertvalue %DualNumber undef, i64 %9, 0
%11 = mul i64 %8, %4
%12 = mul i64 %7, %5
%13 = add i64 %11, %12
%14 = insertvalue %DualNumber %10, i64 %13, 1
store %DualNumber %14, %DualNumber* %0, align 8
ret void
}
julia> @code_native x_i64 * y_i64
.text
Filename: none
Source line: 3
pushq %rbp
movq %rsp, %rbp
Source line: 3
movq (%rsi), %r8
movq 8(%rdx), %rax
Source line: 3
imulq %r8, %rax
Source line: 3
movq (%rdx), %rcx
movq 8(%rsi), %rdx
Source line: 3
imulq %rcx, %rdx
imulq %r8, %rcx
movq %rcx, (%rdi)
addq %rax, %rdx
movq %rdx, 8(%rdi)
movq %rdi, %rax
popq %rbp
ret
julia> x_f64 = DualNumber(1.0, 2.0)
DualNumber{Float64}(1.0,2.0)
julia> y_f64 = DualNumber(3.0, 4.0)
DualNumber{Float64}(3.0,4.0)
julia> @code_llvm x_f64 * y_f64
define void @"julia_*_21344"(%DualNumber.12* sret, %DualNumber.12*, %DualNumber.12*) {
top:
%3 = load %DualNumber.12* %1, align 8
%4 = extractvalue %DualNumber.12 %3, 0
%5 = extractvalue %DualNumber.12 %3, 1
%6 = load %DualNumber.12* %2, align 8
%7 = extractvalue %DualNumber.12 %6, 0
%8 = extractvalue %DualNumber.12 %6, 1
%9 = fmul double %4, %7
%10 = insertvalue %DualNumber.12 undef, double %9, 0
%11 = fmul double %4, %8
%12 = fmul double %5, %7
%13 = fadd double %11, %12
%14 = insertvalue %DualNumber.12 %10, double %13, 1
store %DualNumber.12 %14, %DualNumber.12* %0, align 8
ret void
}
julia> @code_native x_f64 * y_f64
.text
Filename: none
Source line: 3
pushq %rbp
movq %rsp, %rbp
Source line: 3
vmovsd (%rsi), %xmm1
Source line: 3
vmulsd 8(%rdx), %xmm1, %xmm0
Source line: 3
vmovsd (%rdx), %xmm3
Source line: 3
vmulsd 8(%rsi), %xmm3, %xmm2
vmulsd %xmm3, %xmm1, %xmm1
vmovsd %xmm1, (%rdi)
vaddsd %xmm2, %xmm0, %xmm0
vmovsd %xmm0, 8(%rdi)
movq %rdi, %rax
popq %rbp
ret
```
Custom printing for a type can be achieved by extending the `show` function:
```
julia> function Base.show(io::IO, x::DualNumber)
print(io, string(x.value, "+", x.epsilon, "ε"))
end
show (generic function with 98 methods)
julia> DualNumber(1, 2)
1+2ε
```
为类型定义加法和乘法后,在线性代数运算(例如矩阵乘法)中使用此新类型所需的唯一其他方法是定义“零”值,因为Julia具有许多线性代数运算的完全通用实现。
```
julia> Base.zero{T}(::Type{DualNumber{T}}) = DualNumber(zero(T), zero(T))
zero (generic function with 14 methods)
julia> values1 = rand(1:10, 6, 4);
julia> epsilon1 = rand(1:10, 6, 4);
julia> values2 = rand(1:10, 4, 3);
julia> epsilon2 = rand(1:10, 4, 3);
julia> dualmat1 = map(DualNumber, values1, epsilon1)
6x4 Array{DualNumber{Int64},2}:
9+10ε 4+7ε 6+3ε 4+4ε
10+3ε 7+9ε 4+4ε 7+2ε
2+7ε 9+4ε 10+8ε 5+8ε
10+4ε 2+8ε 3+6ε 6+2ε
3+2ε 7+10ε 5+2ε 5+4ε
3+4ε 4+2ε 7+3ε 8+1ε
julia> dualmat2 = map(DualNumber, values2, epsilon2)
4x3 Array{DualNumber{Int64},2}:
6+2ε 2+8ε 4+3ε
5+3ε 5+2ε 10+1ε
3+7ε 5+6ε 3+3ε
1+10ε 6+8ε 2+6ε
julia> dualmat1 * dualmat2
6x3 Array{DualNumber{Int64},2}:
96+220ε 92+242ε 102+200ε
114+216ε 117+257ε 136+209ε
92+245ε 129+256ε 138+183ε
85+191ε 81+240ε 81+195ε
73+184ε 96+196ε 107+183ε
67+191ε 109+177ε 89+129ε
```
双数对优化有非常有用的应用,可以将它们用于自动微分。 有关ForwardDiff.jl软件包的代码夏季报告,请参见http://julialang.org/blog/2015/10/auto-diff-in-julia ,其中包含ForwardDiff.jl软件包的信息,该软件包包含对偶数的综合,高性能实现以及对更高版本的概括。衍生品。
Julia旨在成为两全其美的语言,它提供Python的生产力和可与C ++媲美的性能,并允许从类似C的循环到高级功能抽象的广泛代码风格。 但是,使用越来越多的其他语言存在数百万行现有代码,如果不加以利用,将是愚蠢的。 Julia(Julia)的设计师意识到了这一点,并加入了一些功能以促进与其他语言的互操作性。 从C或Fortran共享库调用函数无需额外的样板代码即可完成,即使从Julia的交互式read-eval-print-loop(REPL)提示符下,也可以轻松使用ccall外部函数接口。
```
julia> ccall((:printf, "libc"), Void, (Cstring, Cstring), "%s\n", "Hello from C printf!")
Hello from C printf!
```
有关更多详细信息,请参见http://docs.julialang.org/en/release-0.4/manual/calling-c-and-fortran-code 。 PyCall.jl(https://github.com/stevengj/PyCall.jl)和JavaCall.jl(https://github.com/aviks/JavaCall.jl)包允许直接调用类似的Python或Java库方式。 通过嵌入LLVM Clang编译器库的C ++库的外部函数接口正在开发中(https://github.com/Keno/Cxx.jl)。
Julia还支持类似Lisp的宏 ,可通过元编程将其用于编程代码生成和特定领域的语言。 可以引用Julia语法并将其表示为表达式数据结构。
Julia使用消息传递多处理模型( http://docs.julialang.org/en/release-0.4/manual/parallel-computing )内置了对分布式内存并行编程的支持。 由于与英特尔实验室的合作,最近将对共享内存多线程的实验支持合并到了开发主机分支中。
Julia版本0.4.0已于10月发布,具有许多新功能,例如缓存已编译的程序包和重写的高性能垃圾收集器。 点发布按月计划进行标记,将错误修正带到稳定的分支中,而master上的新功能是为0.5.0开发的,该功能计划于2016年初发布。通过最终确定标准库接口,该语言正朝着1.0发行。和功能,以及开发功能,例如基于集成LLDB(http://lldb.llvm.org)的调试器和基于Atom(https://atom.io)的编辑器插件和开发环境。 该语言已经非常适用于数据分析和算法开发,并且正在快速开发用于数据库连接,用户界面开发,统计分析,数值优化和可视化的库。 使用HDFS,Hive和MPI库(例如Elemental)进行大规模并行数据分析的软件包是不断发展的Julia生态系统的亮点之一,有关已注册软件包的列表,请参见http://pkg.julialang.org/。
您可以在https://www.juliabox.org的浏览器中尝试使用Julia,或从http://julialang.org/downloads下载最新版本。 该语言是在GitHub上的https://github.com/JuliaLang/julia开发的,邮件列表是https://groups.google.com/forum/#!forum/julia-users。
翻译自: https://www.javacodegeeks.com/2015/12/julia-fresh-approach-numerical-computing-data-science.html
julia语言科学计算