Beberapa konteks di depan tentang dari mana saya berasal. Cuplikan kode ada di akhir.
Ketika saya bisa, saya lebih suka menggunakan alat open source seperti H2O untuk membaca file CSV paralel kinerja tinggi, tetapi alat ini terbatas dalam rangkaian fitur. Saya akhirnya menulis banyak kode untuk membuat jalur data sains sebelum menyuapi cluster H2O untuk pembelajaran yang diawasi dengan baik.
Saya telah membaca file seperti dataset HIGGS 8GB dari repo UCI dan bahkan file CSV 40GB untuk tujuan ilmu data secara signifikan lebih cepat dengan menambahkan banyak paralelisme dengan objek kumpulan pustaka multiprocessing dan fungsi peta. Sebagai contoh pengelompokan dengan pencarian tetangga terdekat dan juga algoritma pengelompokan DBSCAN dan Markov memerlukan beberapa kemahiran pemrograman paralel untuk mem-bypass beberapa masalah memori dan waktu jam dinding yang sangat menantang.
Saya biasanya suka memecah file baris-bijaksana menjadi beberapa bagian menggunakan alat gnu pertama dan kemudian glob-filemask mereka semua untuk menemukan dan membacanya secara paralel dalam program python. Saya menggunakan sesuatu seperti 1000+ file parsial secara umum. Melakukan trik-trik ini sangat membantu dengan kecepatan pemrosesan dan batas memori.
Panda dataframe.read_csv adalah single threaded sehingga Anda dapat melakukan trik ini untuk membuat panda lebih cepat dengan menjalankan peta () untuk eksekusi paralel. Anda dapat menggunakan htop untuk melihat bahwa dengan panda lama berurutan, dataframe.read_csv, 100% cpu hanya pada satu inti adalah hambatan aktual dalam pd.read_csv, bukan disk sama sekali.
Saya harus menambahkan saya menggunakan SSD pada bus kartu video cepat, bukan HD berputar pada SATA6 bus, ditambah 16 core CPU.
Juga, teknik lain yang saya temukan berfungsi dengan baik dalam beberapa aplikasi adalah file CSV paralel membaca semua dalam satu file raksasa, mulai setiap pekerja dengan offset berbeda ke dalam file, daripada memisahkan satu file besar menjadi banyak file bagian. Gunakan file python mencari () dan memberi tahu () pada setiap pekerja paralel untuk membaca file teks besar dalam strip, pada byte berbeda mengimbangi lokasi mulai byte dan akhir byte dalam file besar, semua pada saat yang bersamaan bersamaan. Anda dapat melakukan pencarian regex pada byte, dan mengembalikan jumlah umpan baris. Ini adalah jumlah parsial. Akhirnya jumlahkan jumlah parsial untuk mendapatkan jumlah global ketika fungsi peta kembali setelah pekerja selesai.
Berikut ini adalah beberapa contoh benchmark menggunakan trik byte offset paralel:
Saya menggunakan 2 file: HIGGS.csv adalah 8 GB. Itu dari repositori pembelajaran mesin UCI. all_bin .csv adalah 40,4 GB dan dari proyek saya saat ini. Saya menggunakan 2 program: Program GNU wc yang datang dengan Linux, dan program python fastread.py murni yang saya kembangkan.
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
Itu beberapa 4,5 GB / s, atau 45 Gb / s, file kecepatan menghirup. Itu bukan hard disk yang berputar, temanku. Itu sebenarnya Samsung Pro 950 SSD.
Di bawah ini adalah patokan kecepatan untuk file yang sama yang sedang dihitung baris oleh gnu wc, program yang dikompilasi C murni.
Apa yang keren adalah Anda dapat melihat program python murni saya pada dasarnya cocok dengan kecepatan program C yang dikompilasi gnu wc dalam kasus ini. Python ditafsirkan tetapi C dikompilasi, jadi ini adalah fitur kecepatan yang cukup menarik, saya pikir Anda akan setuju. Tentu saja, wc benar-benar perlu diubah ke program paralel, dan kemudian itu akan benar-benar mengalahkan kaus kaki dari program python saya. Tapi seperti yang ada sekarang, gnu wc hanyalah program berurutan. Anda melakukan apa yang Anda bisa, dan python dapat melakukan paralel hari ini. Kompilasi Cython mungkin dapat membantu saya (untuk beberapa waktu lain). Juga file yang dipetakan memori belum dieksplorasi.
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
Kesimpulan: Kecepatannya baik untuk program python murni dibandingkan dengan program C. Namun, itu tidak cukup baik untuk menggunakan program python murni di atas program C, setidaknya untuk tujuan menghitung linec. Secara umum teknik ini dapat digunakan untuk pemrosesan file lainnya, sehingga kode python ini masih bagus.
Pertanyaan: Apakah mengkompilasi regex hanya satu kali dan memberikannya kepada semua pekerja akan meningkatkan kecepatan? Jawab: Regex pre-compiling TIDAK membantu aplikasi ini. Saya kira alasannya adalah bahwa overhead proses serialisasi dan penciptaan untuk semua pekerja mendominasi.
Satu hal lagi. Apakah pembacaan file CSV paralel bahkan membantu? Apakah disk hambatannya, atau apakah itu CPU? Banyak yang disebut jawaban berperingkat teratas di stackoverflow mengandung kebijaksanaan dev yang umum bahwa Anda hanya perlu satu utas untuk membaca file, terbaik yang bisa Anda lakukan, kata mereka. Apakah mereka yakin?
Mari cari tahu:
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
Oh ya, ya itu. Pembacaan file paralel bekerja dengan sangat baik. Nah begitulah!
Ps. Jika beberapa dari Anda ingin tahu, bagaimana jika balanceFactor adalah 2 ketika menggunakan proses pekerja tunggal? Ya, itu mengerikan:
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
Bagian penting dari program python 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 untuk PartitionDataToWorkers hanyalah kode sekuensial biasa. Saya meninggalkannya untuk berjaga-jaga seandainya ada orang lain yang ingin berlatih seperti apa pemrograman paralel. Saya membagikan secara gratis bagian yang lebih sulit: kode paralel yang diuji dan berfungsi, untuk manfaat belajar Anda.
Terima kasih kepada: Proyek H2O open-source, oleh Arno dan Cliff dan staf H2O untuk perangkat lunak dan video instruksinya yang hebat, yang telah memberi saya inspirasi untuk pembaca offset byte paralel kinerja tinggi python murni ini seperti yang ditunjukkan di atas. H2O melakukan pembacaan file paralel menggunakan java, dapat dipanggil oleh program python dan R, dan gila cepat, lebih cepat dari apa pun di planet ini saat membaca file CSV besar.