Appendix

広告

Entries

Threadを勉強してみた

書くことがないとか言うと書くことが思い浮かぶ不思議・・・

最近、スクリプトの計量化に限界を感じてきたので、今まで使ったことのない機能を勉強しようと思い、そこで目をつけたのがThreadクラスというもの。

名前の通り、スレッドを作るクラスです。
並行プログラミングを可能とするクラスで、つまりはこれにより複数のCPUコアでプログラムを制御する事ができます。
これを身につければ、従来より軽量で多くの処理を行えるんじゃないかと考えたわけです!

(・・・ちなみにRubyに詳しい方なら、この時点で間違ってることに気づくでしょう。
 つまり、そういうお話です)

以前、並列処理を行えるクラスとしてFiberについて書きましたが、あれはプログラムの合間に別の処理を割り込ませる感じです。
こちらの並行処理は、本当に同時に処理を行うらしいです。

例えば、
a = 0
t1 = Thread.new do
  a += 1
end
t2 = Thread.new do
  a += 1
end
t1.join
t2.join
p a
という処理を行った場合。
(joinというのは、スレッドの処理が終わるまで待つメソッドです)

普通に考えると、a は 2 という答えになるはずです。
が、並行処理はこの二つの a += 1 を別々に行うため、2 になることもあれば 1 になることもある
・・・らしいです。(って書いてありました。私は確認してません)

で、これを解決するのが Mutex というクラス。

この Mutex は片方のスレッドでロックをかけると、もう片方のスレッドからはロックできず、ロックが解除されるまでいったん処理を止めてくれるというものです。

スクリプトで書くとこんな感じ。
a = 0
m = Mutex.new
t1 = Thread.new do
  m.lock
  a += 1
  m.unlock
end
t2 = Thread.new do
  m.lock
  a += 1
  m.unlock
end
t1.join
t2.join
p a

これで、a += 1 は片方が終わるまでもう片方は処理されません。
ちゃんと a が 2 という答えを出します。

で、この lock ~ unlock は synchronize { } と簡単なものに置き換えれるようです。
a = 0
m = Mutex.new
t1 = Thread.new do
  m.synchronize { a += 1 }
end
t2 = Thread.new do
  m.synchronize { a += 1 }
end
t1.join
t2.join
p a

・・・が、ここでエラーが発生。
しかも内容は NoMethodError
つまり、Mutex クラスに synchronize なんてメソッドは存在しないよ!ってことです。

訳わかりません。

RGSS3はRuby1.9.2のはずだし、1.9.2には synchronize があるはずです。
試しに methods で定義されているメソッドの配列を表示してみたら、確かに synchronize だけがありません。

結局原因は不明です。
とりあえず、RGSS3の Mutex クラスに synchronize がないのは確かです。
ホントなんででしょう・・・?


話を戻します。

で、これで早速スクリプトの計量化に取り組んだわけですが、なかなかうまく行かない。
RGSSは Graphics.update で1フレームの更新が行われるので、新しく作ったスレッドはこれと同期させなければなりません。
ですが、Mutexは同時に実行するのを防ぐためのものなので、同期をとるのには適していないからです。

ならば、別の方法を考えるしかない。

そこで考えたのが、Thread.stopによる処理の停止と、wakeupによる停止状態の解除です。
a = 0
t = Thread.new do
  loop do
    Thread.stop
    a += 1
  end
end
loop do
  Graphics.update
  t.wakeup
end

こんな感じで組めば、1フレームごとに a を +1 してくれるはずです。

で、これをツクールでやってみたところ、見事同期させることに成功しました!


・・・が、


計量化どころか、明らかにフレームレートが落ちています。
Rubyのスレッドは重いとはどこかで見ましたが、さすがに複数コアでの処理でこれは重すぎるだろう・・・

てか、本当に複数コアで処理してるのでしょうか?

と気になり調べてみましたが、プリエンプティブだかノンプリエンプティブだかグリーンスレッドだかネイティブスレッドだか・・・

私はそういうの、さっぱりわかりません。

ですが、実際に1つのスレッド処理と2つのスレッド処理にかかる時間を比べたものがあり、それによると2つの時は1つの時の倍近い時間がかかるというものでした。

つまり、Rubyは複数コアのCPUでも1つのコアしか使ってないと・・・

実際に私も自家製ベンチマークで処理にかかる時間を測ってみました。


結果・・・


ほんとに2倍の時間がかかってました。

つまり、RGSSではThreadクラスを使っても処理が重くなるだけで、計量化には使えない!

――という、勉強した意味がなかったというお話でした。


でも、将来Threadクラスが複数コアに対応するかもしれないし、
そして次のツクール(出るかどうかは知りません)に最新のRubyが採用されれば、この知識も無駄にはならないでしょう!

そうなるといいな。
スポンサーサイト
この記事にトラックバックする(FC2ブログユーザー)
http://woodpenguin.blog.fc2.com/tb.php/82-c963469c

トラックバック

コメント

[C132]

こんにちは、いつもスクリプトを使わせてもらってます。
メッセージエフェクトで質問があります
文字の大きさを3以上大きくすると文字が切れるのですが、バグなのでしょうか?それとも仕様でしょうか?

  • 2013-09-13 05:08
  • ミュウツタデスオウガ
  • URL
  • 編集

コメントの投稿

コメントの投稿
管理者にだけ表示を許可する

Appendix

プロフィール

木星ペンギン

Author:木星ペンギン
ほぼツクールのことばかり書いてます。
名前は↑から取りました。
木製ですが木星です。
トカゲは関係ありません。

ゲーム

  • 箱庭の勇者たち(体験版)
  • アクイ ト アイ
  • ぼくらの大革命!
  • 勇者がやらねば俺がやる!
  • 3Turn Battle!
  • 3TurnBattle!2nd 体験版

メールフォーム

wood_penguin@yahoo.co.jp

名前:
メール:
件名:
本文: