Scalaの並行処理とアクター、並列コレクション:スケーラブルで関数型でオブジェクト指向なScala入門(10)(3/3 ページ)
Scalaの特徴を紹介し、基本構文や関数、クラスなど、Scalaの基本的な機能について解説する入門連載
Scala 2.9から導入された新機能「並列コレクション」
並列コレクションは、Scala 2.9から導入された比較的新しい機能です。コレクションに対する操作を並列化して別のスレッドで実行する処理を簡単に記述でき、高速に処理できます。
並列コレクションを使用すると、プログラムを実行しているPCのCPUコア数に応じてスレッドを分割して実行します(※並列化のコストも掛かるので、要素数や処理内容によっては遅くなることもあります)。
通常のコレクションと並列コレクションを変換するメソッド
並列コレクションを作成するには、通常のコレクションから変換する方法があります。通常のコレクションに対してparメソッドを使用することで、並列コレクションに変換できます。
scala> Seq(1,2,3).par //並列コレクションに変換 res50: scala.collection.parallel.ParSeq[Int] = ParVector(1, 2, 3)
また、「scala.collection.parallel.immutable」パッケージに並列コレクションクラスが定義されているので、直接並列コレクションのインスタンスも作成できます。並列コレクションのインスタンスに対してseqメソッドを使用すれば、並列コレクションを通常のコレクションに変換できます。
scala> val pList = scala.collection.parallel.immutable.ParSeq(1,2,3) pList: scala.collection.parallel.immutable.ParSeq[Int] = ParVector(1, 2, 3) scala> pList.seq //並列コレクションを通常のコレクションに変換 res49: scala.collection.immutable.Seq[Int] = Vector(1, 2, 3)
通常のコレクションと並列コレクションのパフォーマンスの違い
通常のコレクションと並列コレクションのパフォーマンスを見てみましょう。
まず、各要素に対して処理を実行するexecという関数を定義します。この関数は1秒処理を止め、その後要素を表示するだけの関数です。
def exec(num:Int) = { Thread.sleep(1000) println("num = " + num) }
次に、通常のコレクションを使用した関数を作成しましょう。要素を4つ持つリストを作成し、先ほどのexec関数へ1つずつ要素を渡して実行していきます。
def sum = { val start = System.currentTimeMillis() val list = List(1,2,3,4) for(elem <- list) { exec(elem) } println((System.currentTimeMillis() - start) + " msec") } scala> sum num = 1 num = 2 num = 3 num = 4 4004 msec
筆者の環境で実行すると、4004ミリ秒かかりました。
次に、並列コレクションを使用した関数を作成してみましょう。forループのlistをparで並列コレクションに変換してexecを実行します。
def parSum = { val start = System.currentTimeMillis() val list = List(1,2,3,4) for(elem <- list.par) { exec(elem) } println((System.currentTimeMillis() - start) + " msec") } scala> parSum num = 3 num = 4 num = 1 num = 2 1003 msec
実行してみると、約4分の1の時間で実行が終了しました。これは、筆者の環境で並列化できるスレッド数が4つだからです。並列化できるスレッド数(CPUのコア数)は下記コードを実行すれば取得できます。
scala> scala.collection.parallel.availableProcessors res51: Int = 4 //ここは環境によって異なります
並列コレクションの注意点
このように、並列コレクションは実行にある程度時間がかかり、他の要素の処理結果が関係ない場合に効果を発揮します。ただし、結果を見ると分かるように、処理が終わる順番は保証されないので注意してください。
今後のために、Akkaを試しておこう
さて、今回はScalaの特徴である並行処理用ライブラリと並列コレクションの基本を紹介しました。
本記事内でも述べましたが、Scala 2.10からはscala.actorsの代わりにAkkaが取り込まれる予定です。2.9を使用する場合でも、Scalaで並行処理が必要な場合はAkkaを採用するとメリットが多いので、実際にアプリケーションを開発する際にはAkkaの採用を検討してみてください。
筆者紹介
中村修太(なかむら しゅうた)
クラスメソッド勤務の新しもの好きプログラマーです。昨年、東京から山口県に引っ越し、現在はノマドワーカーとして働いています。好きなJazzを聴きながらプログラミングするのが大好きです。
- カリー化、遅延評価などScalaの文法総まとめ&今後
- Scalaの並行処理とアクター、並列コレクション
- Scalaの抽象型と暗黙の型変換/引数、パラメータ制約
- JavaのGenericsよりも便利なScalaの型パラメータ
- Scalaのトレイトでプログラマをミックスインしてやんよ
- Scalaのパッケージ、アクセス修飾子、オブジェクト継承
- Scalaのクラスとオブジェクト、パターンマッチ
- 基本的なパターンマッチとScalaで重要な“関数”
- Scalaの基本的なコレクション4タイプと制御構文・例外
- Scalaプログラミングで知っておきたい基本構文まとめ
- EclipseでScalaプログラミングを始めるための基礎知識
Copyright © ITmedia, Inc. All Rights Reserved.