「大人の教養・知識・気付き」を伸ばすブログ

一流の大人(ビジネスマン、政治家、リーダー…)として知っておきたい、教養・社会動向を意外なところから取り上げ学ぶことで“気付く力”を伸ばすブログです。データ分析・語学に力点を置いています。 →現在、コンサルタントの雛になるべく、少しずつ勉強中です(※2024年1月21日改訂)。

MENU

Juliaを基礎からゆっくりと(その15/18)

 \mathrm{R}\mathrm{Python}\mathrm{C}言語関係など覚えたいもの、覚えるべきものはたくさんある一方で、注目が集まっているから、やってみたい。ということでプログラミング言語としての\mathrm{Julia}を学んでいく。

4. Juliaの高速化

4.1 プロファイリング

 プログラムを高速化するには、コード処理にかかる時間を計測するプロファイリングが肝要である。プログラムの中で実行に特に時間のかかっている部分をボトルネックという。プロファイリングを行なうことでボトルネックを効率的に発見することが、高速化に向けた第一歩である。

4.1.1 高速化の事前準備

 まずプロファイルを行なう前提として、対象のプログラムが望んだ通りに正しく動作することを確認する。
 次に、その正しい状態を維持するためのテストを用意する。プロファイリング後のチューニングではコードを書き換えるため、誤ってプログラムの動作を変えることを防ぐべくテストは必須である。

 動作確認のテストは可能な限り簡単にできるようにしておく。

例:配列の操作計算
 配列の総和を計算する\mathrm{sum}関数を定義するとしたら、\mathrm{sumtest.jl}などの名称のスクリプトファイルを作成し、\mathrm{sum.jl}ファイルを読み込み、\mathrm{sum}関数のテストを記述する。テスト自体は@\mathrm{assert}マクロを用いると以下のように記述できる。

# sumtest.jl
include("sum.jl")
@assert sum([0]) == 0
@assert sum([1, 2, 3]) == 6

 動作テストには他にレファレンス実装を用意する方法もある。レファレンス実装とは、対象のプログラムや関数と同じ動作をするプログラムを実装することである。

例:自作関数とレファレンス関数の比較

@assert myfunc(arg1, arg2, ...) = reference(arg1, arg2,...)

 プログラムをパッケージとして開発している場合には、パッケージのユニットテストを実行するのが有効である。

 プログラムがデータを入力として取る場合、プロファイリングに用いるサンプルデータも用意する必要がある。このデータは現実に入力として用いられるデータに近い性質を持っていなければならない。また1回のプロファイリングに長い時間がかかる大きなサンプルデータも避けるべきである。
 実用上、データの性質や規模を変えた複数のサンプルデータを用意して性能測定をすべきである。チューニングの結果、あるサンプルデータで性能が向上しても、他のサンプルデータでは著しく性能が劣化することもある。複数のサンプルデータから成るデータセットで行うベンチマークベンチマーク・スイート(\mathrm{benchmark} \mathrm{suite})と呼ばれる。

4.1.2 実行時間の計測

 高速化したいプログラムとテストを用意したら、現在の実行時間を計測する。プロファイルとチューニングの結果、どの程度の高速化が達成できたかはこの実行時間を基準とする。
 実行時間を計測するには、対象を1つの関数にまとめるのがよい。

例:ソート関数の計測*1

using Distributions

xs = randn(100)

@time sort(xs)

@time sort(xs)

@time sort(xs)


 より正確に時間の統計量を計測したければ、\mathrm{BenchmarkTools.jl}を用いるのが望ましい。

using BenchmarkTooks

@benchmark sort(xs)
4.1.3 実行時間のプロファイリング

 プロファイリングを行う際に用いるツールは、標準ライブラリの\mathrm{Profile}モジュールで定義されている。このプロファイラは一定時間ごとにプログラムの動作を止め、その瞬間のスタックトレースを記録し、再度実行に戻る動作を繰り返す。実行時間のかかるホットスポットはこの過程で記録される回数が増えるため、実行時間と記録回数は概ね比例する。

*1:最初はコンパイルが行われるため、例外的に時間がかかっている。

プライバシーポリシー お問い合わせ