เหตุใดการประมวลผลหลายขั้นตอนจึงใช้เพียงคอร์เดียวหลังจากที่ฉันนำเข้าจำนวน


129

ฉันไม่แน่ใจว่าสิ่งนี้นับเป็นปัญหาระบบปฏิบัติการมากกว่าหรือไม่ แต่ฉันคิดว่าฉันจะถามที่นี่ในกรณีที่ใครก็ตามมีความเข้าใจบางอย่างจากจุดสิ้นสุดของ Python

ฉันพยายามขนานforลูปที่ใช้CPU หนักjoblibแต่ฉันพบว่าแทนที่จะกำหนดให้แต่ละกระบวนการของผู้ปฏิบัติงานถูกกำหนดให้กับคอร์ที่แตกต่างกันฉันพบว่ากระบวนการทั้งหมดถูกกำหนดให้อยู่ในคอร์เดียวกันและไม่มีการเพิ่มประสิทธิภาพ

นี่เป็นตัวอย่างที่ไม่สำคัญมาก ...

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

... และนี่คือสิ่งที่ฉันเห็นในhtopขณะที่สคริปต์นี้กำลังทำงาน:

htop

ฉันใช้ Ubuntu 12.10 (3.5.0-26) บนแล็ปท็อปที่มี 4 คอร์ เห็นได้ชัดว่าjoblib.Parallelกำลังวางไข่กระบวนการแยกกันสำหรับคนงานที่แตกต่างกัน แต่มีวิธีใดบ้างที่ฉันสามารถทำให้กระบวนการเหล่านี้ดำเนินการบนคอร์ที่ต่างกันได้


1
stackoverflow.com/questions/15168014/… - ไม่มีคำตอบฉันกลัว แต่ดูเหมือนว่าจะเป็นปัญหาเดียวกัน
NPE

นอกจากนี้ยังstackoverflow.com/questions/6905264/...
NPE


สิ่งนี้ยังคงเป็นปัญหาอยู่หรือไม่? ฉันพยายามสร้างสิ่งนี้ใหม่ด้วย Python 3.7 และนำเข้า numpy ด้วยการประมวลผลหลายขั้นตอน Tool () และใช้เธรดทั้งหมด (ตามที่ควร) เพียงแค่ต้องการให้แน่ใจว่าสิ่งนี้ได้รับการแก้ไขแล้ว
Jared Nielsen

คำตอบ:


149

หลังจาก googling บางมากขึ้นฉันได้พบคำตอบที่นี่

แต่กลับกลายเป็นว่าบางโมดูลหลาม ( numpy, scipy, tables, pandas, skimage... ) ยุ่งกับความสัมพันธ์หลักในการนำเข้า เท่าที่ฉันสามารถบอกได้ปัญหานี้ดูเหมือนจะเกิดจากการเชื่อมโยงกับไลบรารี OpenBLAS แบบมัลติเธรดโดยเฉพาะ

วิธีแก้ปัญหาคือการรีเซ็ตความสัมพันธ์ของงานโดยใช้

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

เมื่อวางบรรทัดนี้หลังจากนำเข้าโมดูลตัวอย่างของฉันตอนนี้ทำงานบนคอร์ทั้งหมด:

htop_workaround

ประสบการณ์ของฉันจนถึงตอนนี้ดูเหมือนว่าสิ่งนี้จะไม่ส่งผลเสียใด ๆ ต่อnumpyประสิทธิภาพการทำงานของฉันแม้ว่านี่อาจจะเป็นเฉพาะเครื่องและงานก็ตาม

ปรับปรุง:

นอกจากนี้ยังมีสองวิธีในการปิดใช้งานพฤติกรรมการรีเซ็ตความสัมพันธ์ของ CPU ของ OpenBLAS เอง ในขณะรันไทม์คุณสามารถใช้ตัวแปรสภาพแวดล้อมOPENBLAS_MAIN_FREE(หรือGOTOBLAS_MAIN_FREE) ตัวอย่างเช่น

OPENBLAS_MAIN_FREE=1 python myscript.py

หรืออีกทางหนึ่งหากคุณกำลังรวบรวม OpenBLAS จากซอร์สคุณสามารถปิดใช้งานได้อย่างถาวรในเวลาสร้างโดยแก้ไขMakefile.ruleเพื่อให้มีบรรทัด

NO_AFFINITY=1

ขอบคุณโซลูชันของคุณช่วยแก้ปัญหาได้ คำถามหนึ่งฉันมีรหัสเดียวกัน แต่ใช้งานต่างกันบนลากเครื่องอื่น ทั้งสองเครื่องคือ Ubuntu 12.04 LTS, python 2.7 แต่มีเพียงเครื่องเดียวเท่านั้นที่มีปัญหานี้ คุณมีความคิดว่าทำไม?
iampat

ทั้งสองเครื่องมี OpenBLAS (สร้างด้วย OpenMPI)
iampat

2
เธรดเก่า แต่ในกรณีที่ใครก็ตามพบปัญหานี้ฉันมีปัญหาแน่นอนและเกี่ยวข้องกับไลบรารี OpenBLAS ดูที่นี่สองวิธีการแก้ปัญหาที่เป็นไปได้และบางส่วนที่เกี่ยวข้องกับการอภิปราย
Gabriel

2
วิธีการตั้งค่าความสัมพันธ์ของซีพียูก็คือการใช้ psutil
Ioannis Filippidis

2
@JHG เป็นปัญหากับ OpenBLAS มากกว่า Python ดังนั้นฉันจึงไม่เห็นเหตุผลใด ๆ ว่าทำไมเวอร์ชัน Python จึงสร้างความแตกต่าง
ali_m

27

Python 3 เปิดเผยวิธีการตั้งค่าความสัมพันธ์โดยตรง

>>> 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
ข้อผิดพลาด> AttributeError: โมดูล 'os' ไม่มีแอตทริบิวต์ 'sched_getaffinity', Python 3.6
Paddy

4
@Paddy จากเอกสารที่เชื่อมโยง: มีให้บริการบนแพลตฟอร์ม Unix บางแพลตฟอร์มเท่านั้น
BlackJack

2
ฉันมีปัญหาเดียวกัน แต่ฉันได้รวมบรรทัดเดียวกันนี้ไว้ที่ระบบปฏิบัติการด้านบน ("tasket -p 0xff% d"% os.getpid ()) แต่ไม่ได้ใช้ cpu ทั้งหมด
rajeshcis

12

Python on Ubuntuนี่หมายความว่ามันทำงานได้โดยไม่มีปัญหาบน Windows และ OS อื่น ๆ ใช่ไหม?
เสา
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.