บริบทบางอย่างล่วงหน้าว่าฉันมาจากไหน ตัวอย่างรหัสอยู่ที่ท้าย
เมื่อฉันสามารถฉันชอบที่จะใช้เครื่องมือโอเพนซอร์สเช่น H2O เพื่ออ่านไฟล์ CSV ขนานประสิทธิภาพสูงเป็นพิเศษ แต่เครื่องมือนี้มีข้อ จำกัด ในชุดคุณลักษณะ ฉันสิ้นสุดการเขียนรหัสจำนวนมากเพื่อสร้างท่อวิทยาศาสตร์ข้อมูลก่อนที่จะส่งไปยังกลุ่ม H2O สำหรับการเรียนรู้ภายใต้การดูแลที่เหมาะสม
ฉันได้อ่านไฟล์เช่นชุดข้อมูล 8GB HIGGS จาก UCI repo และแม้แต่ไฟล์ CSV ขนาด 40GB สำหรับวัตถุประสงค์ด้านวิทยาศาสตร์ข้อมูลได้เร็วขึ้นอย่างมากโดยการเพิ่มความขนานจำนวนมากด้วยฟังก์ชั่นพูลออบเจ็กต์และแผนที่ของมัลติโปรเซสเซอร์ ตัวอย่างเช่นการจัดกลุ่มที่มีการค้นหาเพื่อนบ้านที่ใกล้ที่สุดและอัลกอริทึมการจัดกลุ่ม DBSCAN และ Markov ต้องใช้กลวิธีการเขียนโปรแกรมแบบขนานบางอย่างเพื่อหลีกเลี่ยงปัญหาหน่วยความจำที่ท้าทายอย่างมากและเวลาของนาฬิกาแขวนผนัง
ฉันมักจะชอบแบ่งไฟล์แถวที่ฉลาดออกเป็นส่วน ๆ โดยใช้เครื่องมือ gnu ก่อนจากนั้น glob-filemask พวกเขาทั้งหมดเพื่อค้นหาและอ่านพวกเขาในแบบคู่ขนานในโปรแกรมหลาม ฉันใช้บางอย่างเช่นไฟล์บางส่วนมากกว่า 1,000 ไฟล์ การทำเทคนิคเหล่านี้ช่วยอย่างมากกับการประมวลผลความเร็วและขีด จำกัด ของหน่วยความจำ
pandas dataframe.read_csv เป็นเธรดเดี่ยวดังนั้นคุณสามารถใช้เทคนิคเหล่านี้เพื่อทำให้แพนด้าเร็วขึ้นโดยใช้แผนที่ () สำหรับการประมวลผลแบบขนาน คุณสามารถใช้ htop เพื่อดูว่าด้วยดาต้าต่อเนื่องแบบเก่า ๆ ดาต้าดาต้าสแตร็กซีซี 100% ซีพียูเพียงแกนเดียวคือคอขวดจริงใน pd.read_csv ไม่ใช่ดิสก์เลย
ฉันควรเพิ่มฉันใช้ SSD บนบัสการ์ดแบบเร็วไม่ใช่ HD ที่หมุนได้บนบัส SATA6 บวกกับคอร์ CPU 16 คอร์
อีกเทคนิคหนึ่งที่ฉันค้นพบใช้งานได้ดีในบางแอพพลิเคชั่นคือไฟล์ CSV แบบขนานอ่านทั้งหมดภายในไฟล์ขนาดยักษ์หนึ่งไฟล์โดยเริ่มจากคนงานแต่ละคนที่ออฟเซ็ตต่างกันลงในไฟล์แทนที่จะแยกไฟล์ขนาดใหญ่หนึ่งไฟล์ ใช้ไฟล์ python หา () และ tell () ในแต่ละคนทำงานแบบขนานเพื่ออ่านไฟล์ข้อความขนาดใหญ่ในแถบที่ไบต์ออฟเซ็ตออฟเซตไบต์เริ่มต้นและไบต์สิ้นสุดที่แตกต่างกันในไฟล์ขนาดใหญ่ทั้งหมดในเวลาเดียวกันพร้อมกัน คุณสามารถทำ regex findall บนไบต์และส่งกลับจำนวนของ linefeeds นี่คือผลรวมบางส่วน ในที่สุดก็สรุปผลรวมบางส่วนเพื่อให้ได้ผลรวมทั่วโลกเมื่อฟังก์ชันแผนที่ส่งคืนหลังจากคนงานเสร็จสิ้น
ต่อไปนี้เป็นตัวอย่างมาตรฐานที่ใช้เคล็ดลับออฟเซ็ตไบต์ขนาน:
ฉันใช้ 2 ไฟล์: HIGGS.csv คือ 8 GB มันมาจากแหล่งเก็บข้อมูลการเรียนรู้ของเครื่อง UCI all_bin .csv คือ 40.4 GB และมาจากโครงการปัจจุบันของฉัน ฉันใช้ 2 โปรแกรม: โปรแกรม GNU wc ซึ่งมาพร้อมกับ Linux และโปรแกรม python fastread.py บริสุทธิ์ที่ฉันพัฒนาขึ้น
HP-Z820:/mnt/fastssd/fast_file_reader$ ls -l /mnt/fastssd/nzv/HIGGS.csv
-rw-rw-r-- 1 8035497980 Jan 24 16:00 /mnt/fastssd/nzv/HIGGS.csv
HP-Z820:/mnt/fastssd$ ls -l all_bin.csv
-rw-rw-r-- 1 40412077758 Feb 2 09:00 all_bin.csv
ga@ga-HP-Z820:/mnt/fastssd$ time python fastread.py --fileName="all_bin.csv" --numProcesses=32 --balanceFactor=2
2367496
real 0m8.920s
user 1m30.056s
sys 2m38.744s
In [1]: 40412077758. / 8.92
Out[1]: 4530501990.807175
นั่นคือ 4.5 GB / s หรือ 45 Gb / s ความเร็วของไฟล์ slurping เพื่อนของฉันก็ไม่ได้หมุนฮาร์ดดิสก์เลย นั่นเป็น Samsung Pro 950 SSD จริงๆ
ด้านล่างเป็นเกณฑ์มาตรฐานความเร็วสำหรับไฟล์เดียวกันกับการนับบรรทัดโดย gnu wc ซึ่งเป็นโปรแกรมที่คอมไพล์ด้วย C บริสุทธิ์
อะไรที่เจ๋งมากคือคุณสามารถเห็นโปรแกรมหลามบริสุทธิ์ของฉันตรงกับความเร็วของโปรแกรม C ที่คอมไพล์แล้วในกรณีนี้ Python ตีความได้ แต่ C ถูกคอมไพล์ดังนั้นนี่เป็นเพลงที่น่าสนใจเรื่องความเร็วฉันคิดว่าคุณคงเห็นด้วย แน่นอนว่า wc จำเป็นต้องเปลี่ยนเป็นโปรแกรมคู่ขนานแล้วมันจะเอาชนะถุงเท้าออกจากโปรแกรมไพ ธ อนของฉัน แต่ ณ วันนี้ gnu wc เป็นเพียงโปรแกรมต่อเนื่อง คุณทำสิ่งที่คุณทำได้และหลามสามารถทำขนานกันวันนี้ การรวบรวม Cython อาจช่วยฉันได้ (บางครั้ง) ไฟล์หน่วยความจำที่แมปยังไม่ได้รับการสำรวจ
HP-Z820:/mnt/fastssd$ time wc -l all_bin.csv
2367496 all_bin.csv
real 0m8.807s
user 0m1.168s
sys 0m7.636s
HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=16 --balanceFactor=2
11000000
real 0m2.257s
user 0m12.088s
sys 0m20.512s
HP-Z820:/mnt/fastssd/fast_file_reader$ time wc -l HIGGS.csv
11000000 HIGGS.csv
real 0m1.820s
user 0m0.364s
sys 0m1.456s
สรุป: ความเร็วนั้นดีสำหรับโปรแกรมหลามบริสุทธิ์เมื่อเทียบกับโปรแกรม C อย่างไรก็ตามมันไม่ดีพอที่จะใช้โปรแกรมหลามบริสุทธิ์เหนือโปรแกรม C อย่างน้อยก็เพื่อจุดประสงค์ในการนับจำนวน โดยทั่วไปแล้วเทคนิคนี้สามารถใช้สำหรับการประมวลผลไฟล์อื่น ๆ ดังนั้นรหัสไพ ธ อนนี้จึงยังดี
คำถาม: การรวบรวม regex เพียงครั้งเดียวและส่งให้คนงานทุกคนจะช่วยเพิ่มความเร็วหรือไม่ คำตอบ: การรวบรวมข้อมูลล่วงหน้าของ Regex ไม่ได้ช่วยในแอปพลิเคชันนี้ ฉันคิดว่าเหตุผลก็คือค่าใช้จ่ายในการจัดลำดับกระบวนการและการสร้างสำหรับคนงานทั้งหมดที่มีอำนาจเหนือ
อีกหนึ่งสิ่ง. การอ่านไฟล์ CSV แบบขนานช่วยได้หรือไม่ ดิสก์เป็นคอขวดหรือเป็น CPU หรือไม่ คำตอบที่ได้รับความนิยมสูงสุดใน stackoverflow มีคำสั่ง dev ทั่วไปที่คุณต้องการเพียงหนึ่งเธรดเพื่ออ่านไฟล์ที่ดีที่สุดที่คุณสามารถทำได้พวกเขาพูด พวกเขาแน่ใจเหรอ
ลองดู:
HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=16 --balanceFactor=2
11000000
real 0m2.256s
user 0m10.696s
sys 0m19.952s
HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=1 --balanceFactor=1
11000000
real 0m17.380s
user 0m11.124s
sys 0m6.272s
โอ้ใช่แล้วใช่ การอ่านไฟล์แบบขนานนั้นทำได้ค่อนข้างดี เอาล่ะคุณไปกันแล้ว!
ps ในกรณีที่คุณอยากรู้ว่าถ้า balanceFactor เป็น 2 เมื่อใช้กระบวนการผู้ปฏิบัติงานเดียว ก็น่ากลัว:
HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=1 --balanceFactor=2
11000000
real 1m37.077s
user 0m12.432s
sys 1m24.700s
ส่วนสำคัญของโปรแกรมหลาม fastread.py:
fileBytes = stat(fileName).st_size # Read quickly from OS how many bytes are in a text file
startByte, endByte = PartitionDataToWorkers(workers=numProcesses, items=fileBytes, balanceFactor=balanceFactor)
p = Pool(numProcesses)
partialSum = p.starmap(ReadFileSegment, zip(startByte, endByte, repeat(fileName))) # startByte is already a list. fileName is made into a same-length list of duplicates values.
globalSum = sum(partialSum)
print(globalSum)
def ReadFileSegment(startByte, endByte, fileName, searchChar='\n'): # counts number of searchChar appearing in the byte range
with open(fileName, 'r') as f:
f.seek(startByte-1) # seek is initially at byte 0 and then moves forward the specified amount, so seek(5) points at the 6th byte.
bytes = f.read(endByte - startByte + 1)
cnt = len(re.findall(searchChar, bytes)) # findall with implicit compiling runs just as fast here as re.compile once + re.finditer many times.
return cnt
def สำหรับ PartitionDataToWorkers เป็นเพียงรหัสต่อเนื่องธรรมดา ฉันทิ้งมันไว้ในกรณีที่คนอื่นต้องการฝึกหัดเกี่ยวกับการเขียนโปรแกรมแบบขนาน ฉันแจกส่วนที่ยากขึ้นฟรี: โค้ดทดสอบที่ทำงานและขนานได้เพื่อประโยชน์ในการเรียนรู้ของคุณ
ขอบคุณ: โครงการ H2O แบบโอเพ่นซอร์สโดย Arno และ Cliff และเจ้าหน้าที่ H2O สำหรับซอฟต์แวร์และวิดีโอการเรียนการสอนที่ยอดเยี่ยมของฉันซึ่งเป็นแรงบันดาลใจให้ฉันสำหรับเครื่องอ่าน python ขนานประสิทธิภาพสูงขนานแท้ดังที่แสดงไว้ด้านบน H2O ทำการอ่านไฟล์แบบขนานโดยใช้จาวาสามารถเรียกใช้โดยโปรแกรมหลามและ R และเร็วอย่างบ้าคลั่งเร็วกว่าทุกอย่างในโลกที่อ่านไฟล์ CSV ขนาดใหญ่