Якийсь контекст перед тим, звідки я родом. Фрагменти коду в кінці.
Коли я можу, я вважаю за краще використовувати інструмент з відкритим кодом, як H2O, щоб робити високоефективні паралельні зчитування файлів CSV, але цей інструмент обмежений у наборі функцій. Я закінчую писати багато коду, щоб створити трубопроводи з інформацією, перш ніж подавати в кластер H2O для належного нагляду за навчанням.
Я читав такі файли, як набір даних HIGGS 8 ГБ, з UCI repo і навіть 40 ГБ файлів CSV для цілей наукових даних значно швидше, додаючи багато паралелізму з об'єктом об’єднання пулу та картою багатопроцесорної бібліотеки. Наприклад, кластеризація з найближчим пошуком сусідів, а також алгоритми кластеризації DBSCAN та Маркова вимагає певної паралельної точності програмування для обходу деяких серйозно складних проблем з пам'яттю та настінним годинником.
Я, як правило, люблю розбивати файл на рядок, використовуючи спочатку інструменти gnu, а потім глобальну маску файлів, щоб знайти їх і паралельно прочитати в програмі python. Я зазвичай використовую щось на зразок 1000+ часткових файлів. Виконання цих хитрощів надзвичайно допомагає з обмеженням швидкості обробки та обмеження пам’яті.
Pandas dataframe.read_csv є однопотоковою, тому ви можете виконати ці хитрощі, щоб зробити панди досить швидкими, виконавши карту () для паралельного виконання. Ви можете використовувати htop, щоб побачити, що із простими старими послідовними пандами dataframe.read_csv, 100% процесор на одному ядрі є фактичним вузьким місцем у pd.read_csv, а не на диску взагалі.
Слід додати, що я використовую SSD на швидкій шині відеокарт, а не обертовий HD на шині SATA6, плюс 16 ядер процесора.
Крім того, інша методика, яку я виявив, відмінно працює в деяких додатках, - це паралельний файл CSV, який читає все в одному гігантському файлі, запускаючи кожного працівника з різним зміщенням у файл, а не попередньо розбиваючи один великий файл на багато файлів частини. Використовуйте файл python search () та скажіть () у кожному паралельному працівнику, щоб прочитати великий текстовий файл у смугах, у різних байтових зміщеннях початкового та кінцевого байтів у великому файлі, все одночасно. Ви можете зробити регулярне вираження значень у байтах та повернути кількість ліній каналу. Це часткова сума. Нарешті підсумуйте часткові суми, щоб отримати загальну суму, коли функція карти повернеться після завершення роботи.
Нижче наведено кілька прикладів орієнтирів, що використовують трюк зміщення паралельних байтів:
Я використовую 2 файли: HIGGS.csv - 8 ГБ. Це з сховища машинного навчання UCI. all_bin .csv становить 40,4 Гб і є від мого поточного проекту. Я використовую 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 Гб / с, або 45 Гбіт / с, швидкість шумування файлів. Мій друг, це не жорсткий диск, що обертається. Це насправді SSD Samsung Pro 950.
Нижче наведено орієнтир швидкості для того самого файлу, який підраховується рядком gnu wc, чистою програмою, складеною на C.
Що здорово - це ви можете бачити, що моя чиста програма python в основному відповідала швидкості компільованої програми C gnu wc. Python інтерпретується, але компілюється C, так що це досить цікавий подвиг швидкості, я думаю, ви погодилися б. Звичайно, wc дійсно потрібно змінити на паралельну програму, і тоді він справді бив шкарпетки з моєї програми python. Але, як сьогодні, 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
Висновок: швидкість хороша для чистої програми python порівняно з програмою C. Однак недостатньо добре використовувати програму чистого пітона над програмою C, принаймні для цілей лінійного обліку. Зазвичай техніку можна використовувати для іншої обробки файлів, тому цей код python все ще хороший.
Запитання: Чи збільшить регулярний вираз лише один раз і передасть його всім працівникам, покращить швидкість? Відповідь: Попередня компіляція Regex НЕ допомагає в цій програмі. Я гадаю, що причина полягає в тому, що панує перевага процесів серіалізації та створення для всіх працівників.
І ще одна річ. Чи допомагає паралельне читання файлів CSV? Чи є вузьким місцем диск, чи це процесор? Багато так званих відповідей із найкращими рейтингами щодо stackoverflow містять загальну мудрість розробника, що вам потрібно лише один потік, щоб прочитати файл, що найкраще ви можете зробити, кажуть вони. Але вони впевнені?
Давай дізнаємось:
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
О так, так. Паралельне читання файлів працює досить добре. Ну там ви йдете!
Пс. Якщо хтось із вас захотів знати, що робити, якщо балансFactor був 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 python:
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 за їх чудове програмне та навчальне відео, яке дало мені натхнення для цього чистого високоефективного зчитувача паралельних байтів з компенсацією паралельних байтів, як показано вище. H2O робить паралельне читання файлів за допомогою Java, може викликати програми python та R, і божеволіє швидше, швидше за все на планеті при читанні великих файлів CSV.