Một số bối cảnh phía trước như nơi tôi đến. Đoạn mã ở cuối
Khi tôi có thể, tôi thích sử dụng một công cụ nguồn mở như H2O để đọc tệp CSV song song hiệu suất siêu cao, nhưng công cụ này bị giới hạn trong bộ tính năng. Tôi cuối cùng đã viết rất nhiều mã để tạo ra các đường ống khoa học dữ liệu trước khi cung cấp cho cụm H2O để học tập có giám sát.
Tôi đã đọc các tệp như bộ dữ liệu HIGGS 8GB từ repo UCI và thậm chí các tệp CSV 40 GB cho mục đích khoa học dữ liệu nhanh hơn đáng kể bằng cách thêm nhiều song song với đối tượng nhóm và thư viện của đối tượng đa xử lý. Ví dụ, phân cụm với các tìm kiếm lân cận gần nhất và các thuật toán phân cụm DBSCAN và Markov yêu cầu một số tinh chỉnh lập trình song song để bỏ qua một số vấn đề nghiêm trọng về bộ nhớ và đồng hồ treo tường.
Tôi thường thích chia hàng tệp thành các phần bằng cách sử dụng các công cụ gnu trước và sau đó toàn cầu hóa tất cả chúng để tìm và đọc chúng song song trong chương trình python. Tôi sử dụng một cái gì đó như 1000+ tập tin một phần thường gặp. Làm những thủ thuật này giúp ích rất nhiều với tốc độ xử lý và giới hạn bộ nhớ.
Các dataframe.read_csv của gấu trúc được phân luồng đơn để bạn có thể thực hiện các thủ thuật này để làm cho gấu trúc khá nhanh hơn bằng cách chạy bản đồ () để thực hiện song song. Bạn có thể sử dụng htop để thấy rằng với dataframe.read_csv tuần tự cũ đơn giản, 100% cpu trên chỉ một lõi là nút cổ chai thực sự trong pd.read_csv, hoàn toàn không phải là đĩa.
Tôi nên thêm Tôi đang sử dụng ổ SSD trên bus card video nhanh, không phải HD quay trên bus SATA6, cộng với 16 lõi CPU.
Ngoài ra, một kỹ thuật khác mà tôi phát hiện ra rất hiệu quả trong một số ứng dụng là tệp CSV song song đọc tất cả trong một tệp khổng lồ, bắt đầu mỗi công nhân ở độ lệch khác nhau vào tệp, thay vì chia trước một tệp lớn thành nhiều tệp. Sử dụng tệp tìm kiếm của python () và Tell () trong mỗi nhân viên song song để đọc tệp văn bản lớn theo dải, tại các vị trí bắt đầu byte và byte kết thúc byte khác nhau trong tệp lớn, đồng thời đồng thời. Bạn có thể thực hiện tìm kiếm regex trên byte và trả về số lượng nguồn cấp. Đây là một phần tổng. Cuối cùng tổng hợp một phần tổng để có được tổng toàn cầu khi hàm bản đồ trở lại sau khi các công nhân kết thúc.
Sau đây là một số điểm chuẩn ví dụ sử dụng thủ thuật bù byte song song:
Tôi sử dụng 2 tệp: HIGGS.csv là 8 GB. Nó là từ kho lưu trữ máy học UCI. all_bin .csv là 40,4 GB và là từ dự án hiện tại của tôi. Tôi sử dụng 2 chương trình: chương trình GNU wc đi kèm với Linux và chương trình fastread.txt thuần túy mà tôi đã phát triển.
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
Đó là tốc độ giảm tốc của tệp 4,5 GB / giây hoặc 45 Gb / giây. Đó không phải là đĩa cứng quay, bạn của tôi. Đó thực sự là một ổ SSD Samsung Pro 950.
Dưới đây là điểm chuẩn tốc độ cho cùng một tệp được tính bởi dòng gnu wc, một chương trình được biên dịch C thuần túy.
Điều thú vị là bạn có thể thấy chương trình python thuần của tôi về cơ bản phù hợp với tốc độ của chương trình C được biên dịch gnu wc trong trường hợp này. Python được giải thích nhưng C được biên dịch, vì vậy đây là một kỳ tích khá thú vị về tốc độ, tôi nghĩ bạn sẽ đồng ý. Tất nhiên, wc thực sự cần phải được thay đổi thành một chương trình song song, và sau đó nó sẽ thực sự đánh bật tất khỏi chương trình python của tôi. Nhưng như ngày nay, gnu wc chỉ là một chương trình tuần tự. Bạn làm những gì bạn có thể, và python có thể làm song song ngày hôm nay. Biên dịch Cython có thể có thể giúp tôi (trong một thời gian khác). Ngoài ra các tập tin ánh xạ bộ nhớ chưa được khám phá.
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
Kết luận: Tốc độ tốt cho chương trình python thuần so với chương trình C. Tuy nhiên, nó không đủ tốt để sử dụng chương trình python thuần so với chương trình C, ít nhất là cho mục đích linecounting. Nói chung kỹ thuật có thể được sử dụng để xử lý tệp khác, vì vậy mã python này vẫn tốt.
Câu hỏi: Việc biên dịch regex chỉ một lần và chuyển nó cho tất cả công nhân sẽ cải thiện tốc độ? Trả lời: Biên dịch trước Regex KHÔNG giúp ích gì trong ứng dụng này. Tôi cho rằng lý do là chi phí chung của quá trình tuần tự hóa và sáng tạo cho tất cả các công nhân đang chiếm ưu thế.
Một điều nữa. Việc đọc tệp CSV song song thậm chí có giúp ích không? Đĩa có phải là nút cổ chai hay là CPU? Nhiều câu trả lời được gọi là xếp hạng hàng đầu trên stackoverflow chứa trí tuệ dev phổ biến mà bạn chỉ cần một luồng để đọc tệp, tốt nhất bạn có thể làm, họ nói. Họ có chắc chắn không?
Hãy cùng tìm hiểu:
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
Ồ vâng, vâng, đúng vậy. Đọc tệp song song hoạt động khá tốt. Vâng, bạn đi!
Thi thiên Trong trường hợp một số bạn muốn biết, điều gì sẽ xảy ra nếu thăng bằng 2 khi sử dụng một quy trình công nhân duy nhất? Chà, thật kinh khủng:
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
Các phần chính của chương trình 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 cho PartitionDataToWorkers chỉ là mã tuần tự thông thường. Tôi đã để nó ra ngoài trong trường hợp người khác muốn thực hành một chút về lập trình song song. Tôi đã cho đi miễn phí những phần khó hơn: mã song song được thử nghiệm và hoạt động, vì lợi ích học tập của bạn.
Cảm ơn: Dự án H2O mã nguồn mở, do Arno và Cliff và nhân viên H2O cung cấp cho các video hướng dẫn và phần mềm tuyệt vời của họ, đã cung cấp cho tôi nguồn cảm hứng cho trình đọc bù byte song song hiệu suất cao python thuần như hình trên. H2O thực hiện đọc tệp song song bằng java, có thể gọi được bằng các chương trình python và R, và cực kỳ nhanh, nhanh hơn bất cứ thứ gì trên hành tinh khi đọc các tệp CSV lớn.