0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Julia] マルチプロセスのはまりどころ

Last updated at Posted at 2021-05-14

はじめに

Juliaは、標準ライブラリで手軽にマルチプロセスを実現することができますが、かなり初歩的な部分でハマってしまったのでメモしておきます。以下の二つのエラーに延々ハマっていました。

ERROR: LoadError: On worker 2:
ArgumentError: Package Flux [587475ba-b771-5e3f-ad9e-33799f191a9c] is required but does not seem to be installed:
 - Run `Pkg.instantiate()` to install all recorded dependencies.
ERROR: LoadError: On worker 2:
UndefVarError: #func not defined

結局

  • @everywhereaddprocs の後に書く
  • 仮想環境の場合は、 addprocs(n, exeflags="--project") とする (公式ドキュメント)

正しく動く書き方

using Distributed
using Printf

addprocs(2, exeflags="--project")  # <- project を明示

# @everywhere マクロは addproc の後に書く
@everywhere using Flux

@everywhere function veryHeavyFunc()
    sleep(1)
    return Flux.mae([1.1,1.9,3.1], 1:3)
end

@everywhere function veryVeryHeavyFunc()
    sleep(2)
    return Flux.mse([1.1,1.9,3.1], 1:3)
end

function main()
    s1 = @spawnat 2 veryHeavyFunc()
    s2 = @spawnat 3 veryVeryHeavyFunc()

    r1 = fetch(s1)
    r2 = fetch(s2)

    @printf("r1 = %.5f\n", r1)
    @printf("r2 = %.5f\n", r2)
end

main()

誤った書き方

下のコードは2箇所変更する必要があるので、順に解説します。

using Distributed
using Printf
@everywhere using Flux

@everywhere function veryHeavyFunc()
    sleep(1)
    return Flux.mae([1.1,1.9,3.1], 1:3)
end

@everywhere function veryVeryHeavyFunc()
    sleep(20)
    return Flux.mse([1.1,1.9,3.1], 1:3)
end

function main()
    addprocs(2)

    s1 = @spawnat 2 veryHeavyFunc()
    s2 = @spawnat 3 veryVeryHeavyFunc()

    r1 = fetch(s1)
    r2 = fetch(s2)

    @printf("r1 = %.5f\n", r1)
    @printf("r2 = %.5f\n", r2)
end

main()

誤りその1

main_wrong.jl
using Distributed
using Printf
@everywhere using Flux

@everywhere function veryHeavyFunc()
    sleep(1)
...
end

function main()
    addprocs(2)  # <- wrong!
    
    s1 = @spawnat 2 veryHeavyFunc()
    ....
end

何も考えずに書いたら、新たなプロセスが必要となる箇所付近でプロセスを追加すると思うんですけどねー。これがまずダメでした。 addprocs をした後に @everywhere を付けた関数の定義および using Pacakge を書きましょう。

main_correct.jl
using Distributed
using Printf

addprocs(2)  # <- correct!

@everywhere using Flux

@everywhere function veryHeavyFunc()
    sleep(1)
...
end

function main()
    s1 = @spawnat 2 veryHeavyFunc()
    ....
end

誤りその2

これは公式ドキュメントに書いているので比較的早く気づくことができましたが、

julia --project=/path/to/env main.jl

のように仮想環境を指定して実行している場合、インストールしているパッケージを作成するプロセスでも使用したいのであれば、

addprocs(2, exeflags="--project")

のように第二引数を忘れずに記載しましょう。

別解

コマンドラインで -p 2 などとすれば、コード中に addprocs(2) と書いた時と同じ効果が得られます。
つまり、 addprocs(2, exeflags="--project") とはならないので、残念ながらエラーになります。

julia --project=/path/to/env -p 2 main.jl

ERROR: LoadError: On worker 2:
ArgumentError: Package Flux [587475ba-b771-5e3f-ad9e-33799f191a9c] is required but does not seem to be installed:
 - Run `Pkg.instantiate()` to install all recorded dependencies.
Stacktrace:
[...]

正しく動く書き方(再掲)

using Distributed
using Printf

addprocs(2, exeflags="--project")

@everywhere using Flux

@everywhere function veryHeavyFunc()
    sleep(10)
    return Flux.mae([1.1,1.9,3.1], 1:3)
end

@everywhere function veryVeryHeavyFunc()
    sleep(20)
    return Flux.mse([1.1,1.9,3.1], 1:3)
end

function main()
    s1 = @spawnat 2 veryHeavyFunc()
    s2 = @spawnat 3 veryVeryHeavyFunc()

    r1 = fetch(s1)
    r2 = fetch(s2)

    @printf("r1 = %.5f\n", r1)
    @printf("r2 = %.5f\n", r2)
end

main()

まとめ

juliaの更なる発展に期待!

0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?