目錄

  1. 重要功能
    1. 平行預編譯
    2. 避免重複編譯
    3. 使用者功能
      1. 語法
        1. 增加新的語法 import ... as ...
        2. 可以使用 ... 來指定解構的變數
      2. 陣列與集合
        1. 支援 init 關鍵字參數
        2. 集合容器支援更多運算子
        3. 新的 NamedTuple 建構子
        4. 點運算子可以被用於高階函式
        5. Range 支援非整數型別
      3. 訊息與呈現
        1. @code_XXX 的格式更新
        2. 稀疏矩陣的顯示格式更新
        3. UUID 用裝置亂數作為亂數產生器
    4. 開發者功能
      1. 開發
      2. 二進位檔與函式庫
      3. 測試
      4. 效能調校
        1. 字串支援 view
        2. @time 增加編譯時間比例
  2. 新功能
    1. 新增標準函式庫
    2. 陣列與其他集合
    3. 數值計算
      1. 平行運算
      2. 其他
  3. 新支援
    1. 陣列與其他集合
    2. I/O

在 v1.6 版中,Julia 有大幅度的效能提昇,效能提昇的部份著重在於預編譯(precompilation)以及編譯的效能改進,而 v1.6 版將成為下一個長期支援(long-term support, LTS)的版本。

根據官方部落格,本次版本更新引進了眾多新的技術,包含 parallel precompilation、消除重複編譯、降低編譯器的 latency、加速二進位檔案的載入,以及改善 stacktrace 的格式等等重大的功能。那我們就來詳細看看有哪些更新吧!

重要功能

平行預編譯

使用者在 using/import 某些套件的時候,總是需要等待長久的預編譯時間,但在 v1.6 版引進了平行預編譯(parallel precompilation)技術來降低套件的載入時間。pkg> precompile 會啟動平行預編譯,並且以深度優先的方式,預編譯其套件下的所有相依套件。只有直接相依的套件(列於 Project.toml 中)會丟出錯誤訊息。平行預編譯會在 manifest 被更新之後自動啟動。平行預編譯也支援多套件同時編譯,它會使用多行程(multi-processed)的方式編譯。Julia 會預設地產生最大 CPU 核心數的預編譯任務並且執行平行預編譯。自動預編譯會記住在特定環境下所發生的錯誤,並且會在環境改變時再次嘗試。自動預編譯可以使用 ctrl-c 中斷,或是設定環境變數 JULIA_PKG_PRECOMPILE_AUTO=0 來關閉。

在 v1.5 版載入 DifferentialEquations.jl。

1
2
3
4
5
(v1.5) pkg> add DifferentialEquations
...
julia> @time using DifferentialEquations
[ Info: Precompiling DifferentialEquations [0c46a032-eb83-5123-abaf-570d42b7fbaa]
474.288251 seconds …

在 v1.6 版載入 DifferentialEquations.jl。

1
2
3
4
5
6
7
8
(v1.6) pkg> add DifferentialEquations
...
Precompiling project...
Progress [========================================>] 112/112
112 dependencies successfully precompiled in 72 seconds

julia> @time using DifferentialEquations
4.995477 seconds …

程式碼取自官方部落格。

避免重複編譯

延展性(extensibility)是 Julia 的重要功能之一,你可以對既有的 function 增加新的 method。有的時候,這些更動會讓 Julia 重新編譯程式碼。Julia 會讓「過期」的程式碼被標記,並且編譯新的程式碼。在 v1.6 版中,標記「過期」的程式碼的方式被改進,變得更為精準,如此可以避免重複編譯的問題。

使用者功能

語法

  • Types written with where syntax can now be used to define constructors, e.g.
    (Foo{T} where T)(x) = ....
增加新的語法 import ... as ...

新增新語法 import A as B,也包含import A: x as yimport A.x as yusing A: x as y,可以對載入的模組跟辨識子重新命名。(#1255)

1
2
3
4
5
6
7
julia> import DataFrames as DF

julia> using DataFrames as DF
ERROR: syntax: invalid syntax "using DataFrames as ..."
Stacktrace:
[1] top-level scope
@ none:1

注意,using 是不支援 as 的喔!

可以使用 ... 來指定解構的變數
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
julia> a, b... = [1,2,3]
3-element Vector{Int64}:
1
2
3

julia> a
1

julia> b
2-element Vector{Int64}:
2
3

julia> a, b... = (1,2,3)
(1, 2, 3)

julia> b
(2, 3)

julia> a, b, c... = [1,2,3,4]
4-element Vector{Int64}:
1
2
3
4

julia> c
2-element Vector{Int64}:
3
4

陣列與集合

支援 init 關鍵字參數

sumprodmaximumminimum,以及 count 現在支援 init 關鍵字參數。(#36188, #35839, #37461)

集合容器支援更多運算子

集合容器現在也支援 ∉(collection)∋(item)∌(item) 這些方法。(#38475)

1
2
3
4
5
6
7
8
julia> 1 ∉ [2,3,4]
true

julia> [2,3,4] ∋ 1
false

julia> [2,3,4] ∌ 1
true
新的 NamedTuple 建構子

NamedTuple 有新的建構子,可以用 NamedTuple(iterator) 的方式來支援從 key-value 配對的集合容器中建構 named tuple。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
julia> d = Dict(:a => 1, :b => 2)
Dict{Symbol, Int64} with 2 entries:
:a => 1
:b => 2

julia> NamedTuple(d)
(a = 1, b = 2)

julia> a = [:a => 1, :b => 2]
2-element Vector{Pair{Symbol, Int64}}:
:a => 1
:b => 2

julia> NamedTuple(a)
(a = 1, b = 2)
點運算子可以被用於高階函式
1
2
3
4
5
6
7
julia> map(.*, collect(1:5), collect(6:10))
5-element Vector{Int64}:
6
14
24
36
50
Range 支援非整數型別
1
2
3
4
5
6
7
8
9
10
11
julia> 1.0:0.1:10.0
1.0:0.1:10.0

julia> typeof(1.0:0.1:10.0)
StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}

julia> 1.0:10.0
1.0:1.0:10.0

julia> typeof(1.0:10.0)
StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}

要指定 x:y 以前都需要是整數型別 <: Integer 才行,現在 LinRangeStepRangeStepRangeLen 都支援非整數型別。(#32439)

訊息與呈現

@code_XXX 的格式更新

@code_llvm@code_native 變成彩色的了!

稀疏矩陣的顯示格式更新

稀疏矩陣的顯示變得更直覺了!他自動隱藏非零值。(#33821)

1
2
3
4
5
6
julia> sprand(4, 4, 0.5)
4×4 SparseMatrixCSC{Float64, Int64} with 9 stored entries:
0.883381 0.990356 ⋅ ⋅
0.344935 0.2386460.218795
0.5833950.674894
0.892346 ⋅ ⋅ 0.53169
UUID 用裝置亂數作為亂數產生器

變更 uuid1uuid4 去使用 Random.RandomDevice() 作為預設的亂數產生器。(#35872)

開發者功能

開發

以後不再有 home project 的概念了!執行 julia --project=dir 等同於執行 juliapkg> activate $dir 以及 julia --project 一系列命令。julia --project 等同於指定了 dir = Base.current_project()。(#36434)

編譯與型別推斷現在可以在模組中被啟用或是關閉,使用 Base.Experimental.@compiler_options 可以達到。(#37041)

二進位檔與函式庫

Pkg.Artifacts 模組目前可以被作為一個獨立的套件(Artifacts)使用,當然 Pkg.Artifacts 也可以。(#37320)

Pkg.BinaryPlatforms 被移動至 Base 成為 Base.BinaryPlatforms。(#37320)

如果要延遲下載 artifacts,LazyArtifacts 一定要被列在相依套件中。(#37844)

測試

  • @testset 支援新的選項 verbose 來呈現測試結果。(#33755)

效能調校

字串支援 view

現在所有字串(AbstractString)都支援 view 囉! 也包含 @view 以及 @views,他們會回傳 SubString。(#35879)

1
2
3
4
5
6
7
8
julia> s = "ABCDabcd"
"ABCDabcd"

julia> @view s[2:4]
"BCD"

julia> typeof(@view s[2:4])
SubString{String}
@time 增加編譯時間比例

在執行 @time 時,增加了顯示時間中有多少比例的編譯時間(compile time),@timev 則有更詳盡的資料(#37678)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
julia> A = rand(5, 5)
5×5 Matrix{Float64}:
0.457416 0.437818 0.562112 0.406917 0.447958
0.332568 0.947091 0.936427 0.514941 0.692013
0.590303 0.0198501 0.729961 0.603581 0.333894
0.380095 0.879258 0.957336 0.640208 0.744337
0.313589 0.866007 0.207502 0.480253 0.700147

julia> @time A*A
0.493280 seconds (2.37 M allocations: 127.468 MiB, 7.62% gc time, 97.77% compilation time)
5×5 Matrix{Float64}:
0.981792 1.3718 1.55993 1.22651 1.31208
1.4326 2.11323 2.39394 1.85024 1.98484
1.04164 1.11159 1.53036 1.23779 1.20494
1.50815 2.22566 2.50318 1.9526 2.09605
0.956036 1.9902 1.74374 1.3425 1.65672

julia> @time A*A
0.000007 seconds (1 allocation: 288 bytes)
5×5 Matrix{Float64}:
0.981792 1.3718 1.55993 1.22651 1.31208
1.4326 2.11323 2.39394 1.85024 1.98484
1.04164 1.11159 1.53036 1.23779 1.20494
1.50815 2.22566 2.50318 1.9526 2.09605
0.956036 1.9902 1.74374 1.3425 1.65672

julia> @timev A*A
0.000044 seconds (1 allocation: 288 bytes)
elapsed time (ns): 44371
bytes allocated: 288
pool allocs: 1
5×5 Matrix{Float64}:
0.981792 1.3718 1.55993 1.22651 1.31208
1.4326 2.11323 2.39394 1.85024 1.98484
1.04164 1.11159 1.53036 1.23779 1.20494
1.50815 2.22566 2.50318 1.9526 2.09605
0.956036 1.9902 1.74374 1.3425 1.65672
  • 編譯器最佳化的常數傳遞(constant propagation)支援關鍵字參數(keyword arguments)。(#35976)

新功能

新增標準函式庫

在 v1.6 中,新增了兩個標準函式庫:TOML、Downloads。TOML 可以被用來解析 .toml 檔案。Downloads 提供了跨平台、多協定、行程內的下載功能,並使用 libcurl。它取代了原先的 Base.download,並提供 Downloads.download 介面。

陣列與其他集合

新功能 spdiagm([m, n,] v::AbstractVector) 支援由 v 作為對角線來生成稀疏矩陣的對角矩陣,其呼叫 spdiagm([m, n,] 0 => v),與稠密矩陣的 diagm 有對等的功能。(#37684)

新增 Iterators.map,也新增了 Iterators.map(f, iterators...) 的語法,簡化了 (f(args...) for args in zip(iterators...))。(#34352)

新功能 insorted 來確定一個集合容器中的元素是否是已經排序的。(#37490)

數值計算

現在 isapprox(x,y) 支援 norm 這個關鍵字參數,來計算兩者的範數(norm)是否接近,也支援非陣列的 xy 參數。(#35883)

新功能 LinearAlgebra.BLAS.get_num_threads() 可以取得 BLAS 的執行緒數量。(#36360)

平行運算

新功能 Base.Threads.foreach(f, channel::Channel) 支援多執行緒的 Channel 消耗。(#34543)

其他

新增 parse(::Type{UUID}, ::AbstractString) 方法。

新支援

陣列與其他集合

現在 append!(vector, collections...)prepend!(vector, collections...) 方法都支援多個集合容器(collections)。(#36227)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
julia> a = rand(10);

julia> b = [rand(10), rand(20)]
2-element Vector{Vector{Float64}}:
[0.4274732922161779, 0.10937373891763369, 0.5654187553795427, 0.9906034331313402, 0.013972810993100104, 0.9124867642867496, 0.7026800717485269, 0.6919261624138788, 0.6637048817292697, 0.6751652383396913]
[0.2195233748657055, 0.8611811964575287, 0.5207507597979009, 0.8922624660959817, 0.6598412164100307, 0.5197210219304949, 0.6657337471786067, 0.20595020263413644, 0.9792308729299666, 0.20457512725986682, 0.3964379369245947, 0.9492425568657055, 0.4298200055489003, 0.38595130501514974, 0.9106291942539788, 0.9979619358373388, 0.05452976209666782, 0.7036395889179883, 0.5909806544881551, 0.26667970632080373]

julia> append!(a, b...)
40-element Vector{Float64}:
0.5841916683652206
0.054243862919656216
0.5576101120027053
0.3870928566144738
0.1998130659845283
...

轉置(adjoint!(::*Triangular)transpose!(::*Triangular))一個上(下)三角矩陣 *Triangular 會回傳相反的三角矩陣。套件中含有方法,像是 Adjoint{<:Any,<:LowerTriangular{<:Any,<:OwnMatrixType}} 需要被改為 UpperTriangular{<:Any,<:Adjoint{<:Any,<:OwnMatrixType}}。(#38168)

unique(f, itr; seen=Set{T}()) 現在容許你宣告容器的型別。(#36280)

I/O

redirect_* 函式現在接受 devnull 來拋棄所有輸出的資料,或是作為一個空的輸入來源。(#36146)

redirect_* 函式現在可以呼叫 IOContext 物件。(#36688)