Wizard In The Market
システムトレードの魔術師

*

絶対ダメ! マルチスレッドでの共通変数のインクリメント演算

公開日: : Python , , , , , ,

Hack de Overheid - Apps voor Amsterdam

Photo by Sebastiaan ter Burg

デバッグ中の発見

とあるマルチスレッドプログラムをPythonで書いていた際に遭遇した誤使用です。C/C++等の言語を使った場合には起こらない仕様なので、知っておくと役立つ時がくるはずです。これはPythonだけでなく、Rubyでも同様のことが起こるので、Rubyistさんも是非気をつけていただければと思います。

@ahaha_traderさんのご指摘により、C/C++でも同様のことが発生することを教えていただきました・・・。不勉強をお詫び申し上げます。

このブログを見ているような方々だとバグが生じる実際のコードと、結果をまずお見せしたほうが良いと思うので、サンプル用に作ったコードがこちらです。

バグが生じるソースコード

やっている内容は、12個のスレッドを使って self.increment_count + 1 を12,000回繰り返すという単純処理です。

実行結果

本来、12*1,000の12,000を表示させたかったはずのこのコードなのですが、残念ながら29の違いが生じています。なぜこれが生じてしまうのでしょうか。

動作不良の理由

C/C++など、正式なインクリメントが適応されているような言語ですと、マルチスレッドで行っても、確実にプロセッサレベルで正確にインクリメント処理が行われるので問題がありません。

ですが、PythonやRubyのインクリメント処理は、C/C++で使用されるようなインクリメント処理とはまったく異なります。PythonやRubyの場合のインクリメントの記述自体は、インクリメントっぽく書かれていますが、実際に行われているのは以下の処理です。

ということは、increment_count + 1 の演算が行われた後の結果のPython/Rubyオブジェクトにincrement_countの参照が適応されます。簡単に言うと、演算と結果の格納が2つの処理になってしまっているのです。

この場合、マルチスレッドにて、increment_count + 1 の演算がポインタの割り当てより前に他のスレッドにて同時に行われてしまうというケースが生じます。それが、今回の検証の場合 29/12,000 の割合で生じてしまっていたのですね。

参考URL

誤使用の回避方法

回避する方法は、Queue.Queueクラスを使い、putされた個数を取得するという方法が簡単で便利です(12,000回もカウントするのには実用的ではないけれど)。他にもthreading.Lockを使う方法もありますが、マルチスレッドの利点が減ってしまうかもですね。

なかなかデバッグしにくい内容で手こずりましたが、バグの原因が特定できると納得の行く結果となりました。みなさんもお気をつけ下さいね!

にほんブログ村 為替ブログへ 
Fx-Kirin

About Fx-Kirin

2009年10月にFXを開始、翌年2010年5月から脱サラをしてFX業界に専念。 2012年10月頃から本格的に勝ち始め、一月で資産を倍にする、2年半月間負けなし等、安定した収支で2013年11月に生涯FX収支が1億を超える。 投資スタイルはシステムトレード。プログラミングの知識がほぼない状態から、独学で自分がしたいと思うことであればほぼ実現することが可能なレベルまで成長。好きな言語はRuby, Python。必要となればC++からVBA、Pascal等なんでも行う。MT4/MT5のプログラミングも得意。 2011年にはFXで稼いだ資金をもとにシンガポールに移住し、留学も兼ねて起業をチャレンジするほど、ビジネスを興すことに熱意がある。国内の業者を主に使い始めたことから、2012年に帰国。零細株式会社経営中。

Adsense

  • このエントリーをはてなブックマークに追加
  • Pocket
  • 51 follow us in feedly

関連記事

Pythonのsocketでプロセス間通信をして価格データ等を送信する

どうも、お久しぶりです。キリンです。 取り敢えず1ヶ月ほど、連続でブログの更新を続けてみたのですが、そ

記事を読む

PythonでsleepしているThreadを呼び起こすプラクティス

Pythonのsleep中のThreadをWake up PythonのThreadにて、RubyのThr

記事を読む

重回帰分析による米雇用統計の予測モデルを作成してみる

この記事はPython その2 Advent Calendar 2015 の17日目の記事です。 1 はじめに

記事を読む

ipdb だけではなく IPython.embed も使おう

ipdb だと複数行の挿入ができなかったりするが、その問題が解消される。明らかにこちらのほうが使い勝手がいい。行のデ

記事を読む

no image

stop automatically closeing vim-ipython output with jedi-vim

Even though I commented out the following code in vim_ipytho

記事を読む

Pythonで簡単に画像検出でLinux GUI操作自動化ライブラリを作ったよ

[2015/02/07 追記] [bm url="http://fx-kirin.com/python

記事を読む

PythonのThreadを待機させるか、必要の度に作成するのかのベンチマーク比較

QueueとThreadのベンチマーク比較 2つのケースについて比較検証してみました。 実際に処理する内

記事を読む

Derivatives analytics with Python の学習ノート 1,2章

洋書を読んでいると、いつも読んだ気になってちゃんと理解出来てるか自信がないことが多いので、チャプターごとに要点をまとめ

記事を読む

vim-slime を使って VIM の内容をコンソールに送信

この記事はVim Advent Calendar 2016の20日目の記事です。 選択行の内容をコンソールに送信

記事を読む

Call Python/Numpy Function within Metatrader 4

Github Link [bm url="https://github.com/fx-kirin/mt4-nump

記事を読む

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Adsense

システムトレードを始める前に知っておきたかったこと

今日の勉強会で発表してきました。nbviewer に共有しておきます。 システムトレードを始め

chmod で やらかしてしまったときの対処法

メモ書きです。 find | xargs とかを普通にやってしまうと、すぐに argument

AMD Ryzen & Nvidia GTX 1080 BTO PC 構成・組立と Ubuntu インストール

まだググっても、構成例とか出てないので参考になるんじゃないかなと。機械学習用ですが、全然ゲーム用

Windows のデスクトップアプリをSSHクライアントから再起動する

シェルスプリクト一発で、システムトレードの設定を一括で更新して、MT4を再起動したいとかそういう

UX21A のディスプレイが壊れたので修理

UX21A のディスプレイがぶっ壊れた。 画面にラインが入ったり、ディスプレイが揺れたりするよ

→もっと見る

PAGE TOP ↑