20

注:この質問をよく読んでください。CPython には GIL があることを理解しています。Numpy は通常、ほとんどの機能について GIL によって制限されません。

更新:これは、この質問で説明されている問題と同じであることが判明しました。OpenBLAS に対して numpy をリンクすると、numpy をインポートするとすぐにプロセス全体の CPU アフィニティが設定されます。これは、OpenBLAS ビルドのフラグで修正できます。

私のアプリは、ソースからビルドした numpy を使用しています (つまりeasy_install、 なしなど)。通常、私のカスタム ビルドは問題なく動作します。最近ですが、numpy が複数の CPU コアを使用できないようにする (ビルドに対して? OS に対して?) 何かを行いました。

次のことを行うこの単純なプログラムについて考えてみましょう。

  • ワーカー スレッドでばかげたワークロードを実行します。
  • 2 つの並列スレッドで同じワークロードをさらに 2 回実行します。

適切に動作する numpy インストールでは、2 番目の (並行) ステップは最初のステップとほぼ同じ速さです。しかし、私の特別なビルドでは、2 番目のステップに 2 倍の時間がかかります。使用する CPU は 1 つだけです。numpy.sqrtGIL を解放しないかのように動作していますが、そうすべきであることはわかっています。

男、私が望んでいたとしても、このような派手なビルドを壊す方法がわかりません。複数の CPU コアを使用することを拒否します。どうやってこれをしたのですか?どうすれば修正できますか?

編集:詳細:numpy-1.7.0、gcc、Linux(Fedora 16)ですが、これらの詳細はあまり重要ではないと思います。この問題に遭遇することなく、以前にこの構成で構築しました。このような動作を引き起こす可能性のある特定の OS または python 設定があるかどうか疑問に思っていると思います。

import numpy, threading, time

a1 = numpy.random.random((500,500,200)).astype(numpy.float32)
a2 = numpy.random.random((500,500,200)).astype(numpy.float32)
a3 = numpy.random.random((500,500,200)).astype(numpy.float32)

def numpy_workload(name, a):
    print "starting numpy_workload " + name
    for _ in range(10):
        numpy.sqrt(a)
    print "finished numpy_workload " + name

t1 = threading.Thread(target=lambda: numpy_workload("1", a1))
t2 = threading.Thread(target=lambda: numpy_workload("2", a2))
t3 = threading.Thread(target=lambda: numpy_workload("3", a3))

start = time.time()
t1.start()
t1.join()
stop = time.time()
print "Single thread done after {} seconds\n".format( stop - start )

start = time.time()
t2.start()
t3.start()
t2.join()
t3.join()
stop = time.time()
print "Two threads done after {} seconds\n".format( stop - start )
4

0 に答える 0