Saya mencoba untuk memproses file tab-separated yang cukup besar (~ 30GB). Saya dapat menjalankan awk untuk mengatur ulang kolom, tetapi hanya menggunakan satu inti dari mesin 8 inti saya. Bagaimana saya bisa menggunakan semua core? (dan secara dramatis mengurangi waktu pemrosesan saya) tanpa secara fisik memisahkan file dan menggunakan lebih banyak ruang disk?
cut -f3,4,5,6 original.tsv | awk 'BEGIN { FS="\t" }; { print $2"\t"$1"\t"$3"\t"$4 }' > abridged.tsv
Saya ingin melakukan sesuatu seperti ini, tetapi tanpa menggunakan lebih banyak ruang disk:
split -l 50000 original.tsv sp
for i in $(dir sp*); do ./process_file.sh $i & done;
di mana process_file.sh pada dasarnya adalah pernyataan cut / awk di atas.
Sekali lagi, masalah utama di sini adalah melakukan proses ini tanpa menggunakan 30GB lain! Ada saran?
linux
command-line
MadmenDiver
sumber
sumber
cut
perintah cukup cetak $ 4, $ 3, $ 5, $ 6 (dan atur OFS ke tab)awk
dan beberapa tipu redirection , tapi solusi Perl lebih kuat dalam aspek ini, saya rasa. Selain itu, saat menguji solusinya, pastikan Anda memiliki cadangan file asli (bahkan jika itu 30GB) atau Anda mungkin menyesal.awk
(dan karena itu tidak bisa mengatakan banyak tentang itu) tapi saya pikir itu mungkin mencerahkan diskusi Anda jika saya melempar ini dalam diskusi Anda.Jawaban:
Karena Anda menggunakan "split" untuk memisahkan file Anda dengan jumlah baris, kemudian memprosesnya secara terpisah menghasilkan file yang berbeda (saya kira), Anda bisa melakukan beberapa perintah "awk" yang masing-masing hanya memproses bagian file Anda berdasarkan nomor baris:
NR adalah variabel internal untuk "awk" yang berisi nomor baris saat ini. Setiap perintah hanya akan memproses garis dalam jangkauan mereka. TAPI , mereka semua akan melewati jalur lain juga, karena mereka perlu menghitungnya. Saya cukup yakin itu tidak akan membantu Anda, karena Anda kemungkinan besar akan jatuh dalam kemacetan IO. Tetapi Anda akan memiliki banyak proses, yang memungkinkan Anda untuk menggunakan banyak CPU, jika itu yang Anda inginkan. ;-)
Sekarang, JIKA Anda memiliki semua baris dengan panjang yang sama dalam byte, Anda pasti dapat melakukan paralelisasi nyata. Dalam hal ini, Anda akan menggunakan "dd" untuk mengekstrak porsi yang tepat untuk setiap proses "awk". Anda akan melakukan sesuatu yang mirip dengan:
Di mana 30 adalah jumlah byte di setiap baris. Jika baris Anda tidak semua ukurannya sama dalam byte (yang merupakan kemungkinan terbesar) tapi Anda tahu byte yang tepat di mana blok garis Anda mulai dan berakhir, Anda masih bisa melakukannya menggunakan dd. Pelajari parameternya. Akhirnya, jika Anda tidak tahu di mana blok mulai dan berakhir, Anda dapat menemukannya dengan perintah awk tambahan. Tapi itu menambahkan pembacaan ekstra lengkap dalam file Anda. Kecuali jika Anda akan memproses file original.tsv Anda beberapa kali dengan cara yang berbeda, Anda tentu akan menghabiskan lebih banyak waktu pra-pemrosesan (menghitung byte di mana blok baris dimulai dan berakhir) dan kemudian memproses (yang mungkin akan memiliki keuntungan kecil karena Anda tentu akan memiliki bottleneck IO) daripada jika Anda hanya menggunakan solusi yang sudah Anda ketahui.
Bagaimanapun, sekarang Anda memiliki informasi dan opsi. ;-) Semoga berhasil! (y)
sumber
Fwiw, si
split
perintah memiliki opsi--filter=./myscript.sh
yang memproses data sebelum ditulis ke file keluaran. Jadi, Anda dapat memiliki skrip pra-pemrosesan yang disebut./myscript.sh
mengandung transformasi Anda, mis.,dimana
$FILE
adalah file output yang dihasilkan olehsplit
(misalnyaxaa
, ...). Atau, untuk menghindari semua file temp, cukup menyatukan ke satu file,Tidak ada alasan untuk percaya ini akan lebih cepat daripada tidak menggunakan
split
Namun demikian.Mempertimbangkan bahwa Anda sedang melakukan pemrosesan "data besar" (dan berapa tahun setelah pertanyaan ini awalnya diajukan), mungkin juga mudah untuk menyalin file 30GB ini ke HDFS (atau, lebih tepatnya, menempatkan & menyimpan data tersebut) ada awalnya) dan gunakan sarang apache untuk memilih / memformat data yang diinginkan.
sumber