Mengapa multiprosesing hanya menggunakan satu inti setelah saya mengimpor numpy?

127

Saya tidak yakin apakah ini dianggap lebih sebagai masalah OS, tapi saya pikir saya akan bertanya di sini kalau-kalau ada yang memiliki wawasan dari akhir Python.

Saya telah mencoba untuk memparalelkan penggunaan CPU-heavy forloop joblib, tetapi saya menemukan bahwa alih-alih setiap proses pekerja ditugaskan ke inti yang berbeda, saya berakhir dengan semuanya ditugaskan ke inti yang sama dan tidak ada peningkatan kinerja.

Inilah contoh yang sangat sepele ...

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()

... dan inilah yang saya lihat htopsaat skrip ini berjalan:

htop

Saya menjalankan Ubuntu 12.10 (3.5.0-26) pada laptop dengan 4 core. Jelas joblib.Parallelsedang memunculkan proses terpisah untuk pekerja yang berbeda, tetapi apakah ada cara saya bisa membuat proses ini dijalankan pada core yang berbeda?

ali_m
sumber
stackoverflow.com/questions/15168014/... - tidak ada jawaban di sana saya takut, tapi kedengarannya seperti masalah yang sama.
NPE
Apakah ini masih menjadi masalah? Saya mencoba untuk membuat ulang ini dengan Python 3.7 dan mengimpor numpy dengan multiprocessing.Pool (), dan menggunakan semua utas (sebagaimana mestinya). Hanya ingin memastikan bahwa ini sudah diperbaiki.
Jared Nielsen

Jawaban:

148

Setelah googling lagi saya menemukan jawabannya di sini .

Ternyata modul Python tertentu ( numpy, scipy, tables, pandas, skimage...) berantakan dengan afinitas inti pada impor. Sejauh yang saya tahu, masalah ini tampaknya secara khusus disebabkan oleh mereka yang terhubung dengan pustaka OpenBLAS multithreaded.

Solusinya adalah mereset afinitas tugas menggunakan

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

Dengan baris ini disisipkan setelah impor modul, contoh saya sekarang berjalan pada semua core:

htop_workaround

Pengalaman saya sejauh ini adalah bahwa ini tampaknya tidak memiliki efek negatif pada numpykinerja, meskipun ini mungkin khusus untuk mesin dan tugas.

Memperbarui:

Ada juga dua cara untuk menonaktifkan perilaku reset-afinitas CPU dari OpenBLAS itu sendiri. Saat run-time Anda dapat menggunakan variabel lingkungan OPENBLAS_MAIN_FREE(atau GOTOBLAS_MAIN_FREE), misalnya

OPENBLAS_MAIN_FREE=1 python myscript.py

Atau sebagai alternatif, jika Anda mengkompilasi OpenBLAS dari sumber, Anda dapat menonaktifkannya secara permanen saat membangun dengan mengedit Makefile.ruleagar mengandung baris

NO_AFFINITY=1
ali_m
sumber
Terima kasih, solusi Anda menyelesaikan masalah. Satu pertanyaan, saya memiliki kode yang sama tetapi berjalan secara berbeda di belakang mesin yang berbeda. Kedua mesin adalah Ubuntu 12.04 LTS, python 2.7, tetapi hanya satu yang memiliki masalah ini. Apakah Anda tahu mengapa?
iampat
Kedua mesin memiliki OpenBLAS (build with OpenMPI).
iampat
2
Utas lama, tetapi jika ada orang lain yang menemukan masalah ini, saya memiliki masalah yang pasti dan itu memang terkait dengan perpustakaan OpenBLAS. Lihat di sini untuk dua kemungkinan penyelesaian dan beberapa diskusi terkait.
Gabriel
2
Cara lain untuk mengatur afinitas cpu adalah menggunakanpsutil .
Ioannis Filippidis
2
@JHG Ini masalah dengan OpenBLAS daripada Python, jadi saya tidak bisa melihat alasan mengapa versi Python akan membuat perbedaan
ali_m
27

Python 3 sekarang memaparkan metode untuk secara langsung mengatur afinitas

>>> 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}
WoJ
sumber
1
Kesalahan> AttributeError: modul 'os' tidak memiliki atribut 'sched_getaffinity', Python 3.6
Paddy
4
@ Paddy Dari dokumentasi tertaut: Mereka hanya tersedia di beberapa platform Unix.
BlackJack
2
Saya memiliki masalah yang sama tetapi saya telah mengintegrasikan baris yang sama ini di sistem os.system atas ("tasket -p 0xff% d"% os.getpid ()) tetapi tidak menggunakan semua cpu
rajeshcis