pythonのthreadingを使いクーロン力の並列計算をするテスト

以前行った、multiprocessingでのクーロン力並列計算に引き続き、threadingを使ったクーロン力の並列計算をテストする。計算条件はmultiprocessingの時と同じくcore数を4、計算粒子数を15^3個とした。

結果、計算時間は14.36[sec]。multiprocessingでの計算は2.09[sec]であったため、大分時間がかかるというかシングルスレッドで計算していた時より時間がかかっている。threadingでは各threadがメモリを共有するために必要な情報を取得するためメモリアクセスする際に、排他ロック(GIL)が起きているのかな、と考えられる。試しにthread数を1にして実行してみると処理時間は6.92[sec]。thread化しない方が高速であった。

■結果 [Results summary]

code type 時間[sec]
threading (4threads) 14.36 <-(new!)
threading (1thread) 6.92 <-(new!)
multiprocessing 2.09
itertools使用 (no1) 8.18
range記述 (no2) 7.93
xrange記述 (no3) 7.89
ループ内周でnumpy使用 (no4) 78.46

■使用したコードは下記(use 4 threads)

Following previous parallel computation of Coulomb force in multiprocessing, we test parallel computation of Coulomb force using threading. The same condition as before the multiprocessing calculation condition, the core number was set to 4 and the number of calculated particles was set to 15 ^ 3.

As a result, the calculation time is 14.36 [sec]. The computation with multiprocessing was 2.09 [sec], so it took a long time or it took more time than when computing with single thread. In threading, it is considered that an exclusive lock (GIL) is occurring when memory access is performed in order to acquire necessary information for each thread to share memory. If we try to run with thread number 1, the processing time is 6.92 [sec]. It was faster to not thread.

マルチスレッドのテスト

スレッドを発行して並列化するテスト。スレッドの開始はstart(),終了待ちはjoin()で行う。すべてのスレッドの終了をチェックするためには、現在発行中の全スレッドをリストアップするenumerate()を使う。ただしこのリストの中には、メインスレッドも含まれているので、メインスレッドは抜く必要がある。メインスレッドはcurrentThread()であらわせるので、これをremoveで取り除く。取り除いた結果に対して、join()で終了待ちし、全スレッドが終了したら終了メッセージを出す。各スレッドからの返り値はQueueを使って貯めることができる。貯めたいqueueを引数に渡してやることで、スレッド終了後に全スレッドの結果を読み出すことができる。

■実行結果
thread = 0 rand = 1.97370804812
thread = 1 rand = 3.45525477664
thread = 2 rand = 0.651252139145
thread = 3 rand = 3.96551177159
thread = 4 rand = 3.57845628232
thread = 5 rand = 1.81758678574
thread = 6 rand = 2.31490107118
thread = 7 rand = 1.21471678276
end thread = 2
end thread = 7
end thread = 5
end thread = 0
end thread = 6
end thread = 1
end thread = 4
end thread = 3
[0.6512521391445797, 1.2147167827645151, 1.817586785739616, 1.9737080481200742, 2.3149010711817626, 3.4552547766386787, 3.5784562823201704, 3.9655117715879653]
end

A test that issues threads and parallelizes them. The start of the thread is done with start (), and the wait for completion is done with join (). To check the termination of all threads, use enumerate () which lists all the threads that are currently issuing. However, since the main thread is also included in this list, it is necessary to withdraw the main thread. The main thread can be set with currentThread (), so remove it with remove. Wait for join () to finish removing, and issue a termination message when all threads are finished. The return value from each thread can be stored using Queue. By passing the queue you want to save as an argument, you can read the results of all threads after the thread ends.