Ben numpy'yi içe aktardıktan sonra çoklu işlem neden yalnızca tek bir çekirdek kullanıyor?


129

Bunun bir işletim sistemi sorunu olarak sayılıp sayılmayacağından emin değilim, ancak herhangi birinin Python'un sonundan bir fikir edinmesi durumunda soracağımı düşündüm.

İşlemci ağırlıklı bir fordöngüyü kullanarak paralel hale getirmeye çalışıyorum joblib, ancak her çalışan işlemin farklı bir çekirdeğe atanması yerine, hepsinin aynı çekirdeğe atandığını ve hiçbir performans kazanmadığımı görüyorum.

İşte çok önemsiz bir örnek ...

from joblib import Parallel,delayed
import numpy as np

def testfunc(data):
    # some very boneheaded CPU work
    for nn in xrange(1000):
        for ii in data[0,:]:
            for jj in data[1,:]:
                ii*jj

def run(niter=10):
    data = (np.random.randn(2,100) for ii in xrange(niter))
    pool = Parallel(n_jobs=-1,verbose=1,pre_dispatch='all')
    results = pool(delayed(testfunc)(dd) for dd in data)

if __name__ == '__main__':
    run()

... ve işte htopbu komut dosyası çalışırken gördüklerim :

htop

4 çekirdekli bir dizüstü bilgisayarda Ubuntu 12.10 (3.5.0-26) çalıştırıyorum. Açıkçası joblib.Parallelfarklı çalışanlar için ayrı süreçler üretiyor, ancak bu süreçlerin farklı çekirdeklerde yürütülmesini sağlamanın bir yolu var mı?


1
stackoverflow.com/questions/15168014/… - orada yanıt yok Korkarım ama aynı sorun gibi geliyor.
NPE



Hala böyle bir mesele var mı? Bunu Python 3.7 ile yeniden oluşturmaya çalışıyorum ve numpy'yi multiprocessing.Pool () ile içe aktarmaya çalışıyorum ve (olması gerektiği gibi) tüm iş parçacıkları kullanıyor. Sadece bunun düzeltildiğinden emin olmak istiyorum.
Jared Nielsen

Yanıtlar:


149

Biraz daha googling yaptıktan sonra cevabı burada buldum .

O (yani belli Python modülleri çıkıyor numpy, scipy, tables, pandas,skimage ithalat çekirdek afinite ile ...) karışıklık. Anladığım kadarıyla, bu sorun özellikle çok iş parçacıklı OpenBLAS kitaplıklarına bağlanmalarından kaynaklanıyor gibi görünüyor.

Geçici bir çözüm, kullanarak görev benzeşimini sıfırlamaktır.

os.system("taskset -p 0xff %d" % os.getpid())

Modül içe aktarıldıktan sonra bu satır yapıştırıldığında, örneğim artık tüm çekirdeklerde çalışıyor:

htop_workaround

Şimdiye kadarki deneyimim numpy, muhtemelen makineye ve göreve özgü olsa da, bunun performansı üzerinde herhangi bir olumsuz etkiye sahip olmadığı yönünde olmuştur .

Güncelleme:

OpenBLAS'ın CPU benzeşimini sıfırlama davranışını devre dışı bırakmanın da iki yolu vardır. Çalışma zamanında ortam değişkenini OPENBLAS_MAIN_FREE(veya GOTOBLAS_MAIN_FREE) kullanabilirsiniz, örneğin

OPENBLAS_MAIN_FREE=1 python myscript.py

Veya alternatif olarak, OpenBLAS'ı kaynaktan derliyorsanız Makefile.rule, satırı içerecek şekilde düzenleyerek derleme zamanında kalıcı olarak devre dışı bırakabilirsiniz.

NO_AFFINITY=1

Teşekkürler, çözümünüz sorunu çözdü. Bir soru, aynı koda sahibim ama farklı bir makinede farklı çalışıyorum. Her iki makine de Ubuntu 12.04 LTS, python 2.7, ancak yalnızca birinde bu sorun var. neden olduğu hakkında bir fikrin var mı?
iampat

Her iki makinede de OpenBLAS vardır (OpenMPI ile derlenir).
iampat

2
Eski iş parçacığı, ancak başka birinin bu sorunu bulması durumunda, tam olarak sorunu yaşadım ve bu gerçekten OpenBLAS kitaplıklarıyla ilgiliydi. İki olası geçici çözüm ve ilgili bazı tartışmalar için buraya bakın .
Gabriel

2
Cpu benzeşimini ayarlamanın başka bir yolu kullanmaktırpsutil .
Ioannis Filippidis

2
@JHG Bu Python yerine OpenBLAS ile ilgili bir sorun, bu yüzden Python sürümünün neden bir fark yaratacağına dair herhangi bir neden göremiyorum
ali_m

27

Python 3 artık yakınlığı doğrudan ayarlamak için yöntemleri ortaya koyuyor

>>> import os
>>> os.sched_getaffinity(0)
{0, 1, 2, 3}
>>> os.sched_setaffinity(0, {1, 3})
>>> os.sched_getaffinity(0)
{1, 3}
>>> x = {i for i in range(10)}
>>> x
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
>>> os.sched_setaffinity(0, x)
>>> os.sched_getaffinity(0)
{0, 1, 2, 3}

1
Hata> AttributeError: 'os' modülünün 'sched_getaffinity' niteliği yok, Python 3.6
Paddy

4
@Paddy Bağlantılı belgelerden: Bunlar yalnızca bazı Unix platformlarında mevcuttur.
BlackJack

2
Aynı problemim var ama aynı satırı üst os.system'e ("tasket -p 0xff% d"% os.getpid ()) entegre ettim ama tüm
cpu'yu kullanmıyor

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.