# Julia で multithreading

# Overview

  • multithreading とは並列処理のことで、複数の互いに依存しない処理を同時に処理する仕組みのことです。これは複数コアを搭載している CPU であれば実現可能で、どのプログラミング言語でも大抵実現可能です。

  • Julia では multhreading 処理を v1.3.0-alpha から利用可能で、multi-thread は論理コア数(=スレッド数)を指定することでそのスレッド数分、計算に使うことができます。

  • やはり処理を分配する処理にはオーバーヘッドがあり、それぞれのスレッドにさせる処理のサイズが小さすぎると逆に処理が遅くなります。

# Requirements

  • マルチコアな CPU を搭載した環境
  • Julia v1.3.0-alpha

# Main

# コア数の確認方法

  • mac
    • $ sysctl -n hw.logicalcpu
  • linux
    • $ fgrep 'processor' /proc/cpuinfo | wc -l

# 設定

  • mac
    $ echo "export JULIA_NUM_THREADS=`sysctl -n hw.logicalcpu`" >> ~/.zshrc
    
  • linux
    $ THREADS=`fgrep 'processor' /proc/cpuinfo | wc -l
    $ echo "export JULIA_NUM_THREADS=$THREADS" >> ~/.bashrc
    

このように設定をし、以下のように julia を起動、または実行します。

$ julia hogehuga.jl [あなたの素敵な引数] -u auto   # hogehuga.jlを実行
$ julia -t auto                                 # .zshrc(.bashrc)に記載されたthread数を起動
$ julia --threads 4                             # 指定したthread数を起動
$ julia -t 4                                    # 指定したthread数を起動
$ JULIA_NUM_THREADS=4 julia                     # 指定したthread数を起動

multithread が使えるようになったかどうかは

julia> Threads.nthreads()
4

とすることで起動した thread 数を確認して、判断する。

# script

julia の並列処理は Base に含まれる Thread package で行うことができる。

# 並列処理

function main()
    println("Thread数: ", Threads.nthreads())
    Threads.@threads for i = 1:20
        sleep(1)
        println(i)
    end
end

p, t = @timed main()
println("実行時間: ", t)
$ julia -t 8
Thread数: 8
7
13
10
... (中略)
9
12
3
6
(value = nothing, time = 3.072258373, bytes = 3019730, gctime = 0.0, gcstats = Base.GC_Diff(3019730, 0, 0, 54596, 14, 0, 0, 0, 0))

> 実行時間: 3.072258373

# 逐次処理

function main()
    for i = 1:20
        sleep(1)
        println(i)
    end
end

p, t = @timed main()
println("実行時間: ", t)
$ julia
1
2
3
... (中略)
19
20
(value = nothing, time = 20.103233506, bytes = 695522, gctime = 0.0, gcstats = Base.GC_Diff(695522, 0, 0, 13384, 1, 0, 0, 0, 0))
> 実行時間: 20.103233506

# summarize

アムダールの法則より、並列処理による性能向上はNN個のプロセッサを利用し、プログラムの並列化した部分の実行時間の割合をPPとすると全体の性能向上率S(N)S(N)

S(N)=1(1P)+PNS(N) = \frac{1}{(1-P) + \frac{P}{N}}

であることが知られています。

参照: 並列処理で、どういうときにパフォーマンスがあがるのか(理論) : 並行処理、並列処理のあれこれ - Qiita (opens new window)

つまり、並列化できる割合を大きくすべきで、また並列化による処理高速化は限界があることも頭に入れておかなければなりません。

しかし上のように、処理のほとんどを並列化している Julia プログラムは 1/20 程度まで高速化が見込めるため、並列化は非常に有効であることが考えられます。 他言語では並列化の処理は非常に難易度が高くスキルが必要ですが、Julia では上のように非常に容易に実装することができます。

# Reference

並行処理、並列処理のあれこれ - Qiita (opens new window)

Julia プログラミングクックブック ―言語仕様からデータ分析、機械学習、数値計算まで (opens new window)

The-@threads-Macro Multi-Threading · The Julia Language (opens new window)

Last Updated: 12/6/2021, 7:41:52 PM