Nereden geldiğime dair bazı bağlamlar ön plana çıkıyor. Kod parçacıkları sonunda.
Mümkün olduğunda, süper yüksek performanslı paralel CSV dosyası okumak için H2O gibi bir açık kaynak aracı kullanmayı tercih ederim, ancak bu araç özellik kümesinde sınırlıdır. Denetimli öğrenme için H2O kümesine beslenmeden önce veri bilimi boru hatları oluşturmak için bir sürü kod yazıyorum.
Çok işlemli kütüphanenin havuz nesnesi ve harita fonksiyonu ile çok sayıda paralellik ekleyerek veri bilimi amaçlı 8GB HIGGS veri seti ve hatta 40GB CSV dosyaları gibi dosyaları çok daha hızlı okuyorum. Örneğin, en yakın komşu aramalarıyla ve ayrıca DBSCAN ve Markov kümeleme algoritmalarıyla kümeleme, bazı ciddi zorlayıcı bellek ve duvar saati zaman sorunlarını atlamak için bazı paralel programlama inceliği gerektirir.
Genellikle dosyayı ilk önce gnu araçlarını kullanarak parçalara ayırmayı ve sonra bunları python programında paralel olarak bulup okumak için glob-filemask etmeyi severim. Genelde 1000'den fazla kısmi dosya gibi bir şey kullanıyorum. Bu hileleri yapmak, işlem hızı ve bellek sınırlarına son derece yardımcı olur.
Panda dataframe.read_csv tek iş parçacıklı olduğundan, paralel yürütme için bir harita () çalıştırarak pandaları daha hızlı hale getirmek için bu hileleri yapabilirsiniz. Düz eski sıralı pandalar dataframe.read_csv ile, sadece bir çekirdekteki% 100 cpu'nun disk değil, pd.read_csv'deki gerçek darboğaz olduğunu görmek için htop'u kullanabilirsiniz.
SATA6 veriyolunda dönen bir HD değil, 16 CPU çekirdeği yerine hızlı video kartı veriyolunda SSD kullanıyorum.
Ayrıca, bazı uygulamalarda harika çalıştığını keşfettiğim başka bir teknik, büyük bir dosyayı birçok parça dosyasına önceden bölmek yerine, her bir çalışanı farklı bir ofsetle başlatan, bir CSP dosyası okuyor. Büyük dosyadaki farklı bayt uzaklığı başlangıç bayt ve bitiş bayt konumlarında, aynı anda aynı anda büyük metin dosyasını şeritler halinde okumak için her paralel çalışanda python'un file seek () ve tell () işlevlerini kullanın. Baytlar üzerinde regex findall yapabilir ve satır besleme sayısını döndürebilirsiniz. Bu kısmi bir meblağdır. Son olarak, harita işlevi çalışanlar bittikten sonra döndüğünde küresel toplamı elde etmek için kısmi toplamları toplayın.
Paralel bayt ofset hilesi kullanan bazı örnek karşılaştırmalar:
2 dosya kullanıyorum: HIGGS.csv 8 GB. UCI makine öğrenim deposundan. all_bin .csv 40.4 GB ve şu anki projemden. 2 program kullanıyorum: Linux ile birlikte gelen GNU wc programı ve geliştirdiğim saf python fastread.py programı.
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
Bu yaklaşık 4,5 GB / sn veya 45 Gb / sn dosya sıkıştırma hızıdır. Dönen bir sabit disk değil dostum. Bu aslında bir Samsung Pro 950 SSD.
Aşağıda, aynı dosya için saf C derlenmiş bir program olan gnu wc tarafından sayılan hız karşılaştırması yer almaktadır.
Güzel olan şey, bu durumda saf python programımın gnu wc derlenmiş C programının hızıyla eşleştiğini görebilirsiniz. Python yorumlanır, ancak C derlenir, bu yüzden bu oldukça ilginç bir hız başarısıdır, bence kabul edersiniz. Tabii ki, wc'nin gerçekten paralel bir programa değiştirilmesi gerekiyor ve daha sonra çorapları python programımdan gerçekten yenecekti. Ancak bugün olduğu gibi, gnu wc sadece sıralı bir programdır. Yapabileceğinizi yaparsınız ve python bugün paralel yapabilir. Cython derlemesi bana yardımcı olabilir (başka bir süre için). Ayrıca bellek eşlemeli dosyalar henüz araştırılmadı.
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
Sonuç: Hız, saf bir python programı için C programına kıyasla iyidir. Bununla birlikte, saf python programını en azından satır sayımı amacıyla C programı üzerinde kullanmak yeterli değildir. Genellikle teknik diğer dosya işleme için kullanılabilir, bu nedenle bu python kodu hala iyidir.
Soru: Normal ifadeyi bir kez derlemek ve tüm işçilere aktarmak hızı artıracak mı? Yanıt: Regex ön derlemesi bu uygulamada YARDIMCI OLMAZ. Bunun nedeni, tüm çalışanlar için süreç serileştirme ve yaratma yükünün baskın olmasıdır.
Bir şey daha. Paralel CSV dosyası okuması bile yardımcı olur mu? Disk darboğaz mı yoksa CPU mu? Stackoverflow üzerinde birçok üst düzey cevaplar, bir dosyayı okumak için sadece bir iş parçacığına ihtiyacınız olan ortak geliştirme bilgisini içerir, en iyi yapabileceğinizi söylüyorlar. Yine de eminler mi?
Hadi bulalım:
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 evet, evet öyle. Paralel dosya okuma oldukça iyi çalışır. İyi gidiyorsun!
Ps. Bazılarınızın bilmek istediği durumlarda, tek bir çalışan işlemi kullanırken balanceFactor 2 olsaydı? Korkunç:
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 programının önemli bölümleri:
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
PartitionDataToWorkers için def sıradan bir sıralı koddur. Bir başkasının paralel programlamanın nasıl olduğu konusunda biraz pratik yapmak istemesi durumunda bunu bıraktım. Daha zor kısımları ücretsiz olarak verdim: öğrenme yararınız için test edilmiş ve çalışan paralel kod.
Teşekkürler: Arno ve Cliff ve H2O personeli tarafından, yukarıda gösterildiği gibi bu saf python yüksek performanslı paralel bayt ofset okuyucu için ilham veren harika yazılım ve eğitim videoları için açık kaynaklı H2O projesi. H2O, java kullanarak paralel dosya okuması yapar, python ve R programları tarafından çağrılabilir ve büyük CSV dosyalarını okurken gezegendeki her şeyden daha hızlıdır.