Parsing 25TB nganggo AWK sareng R

Parsing 25TB nganggo AWK sareng R
Kumaha maca artikel ieu: Hapunten bilih tulisanna panjang sareng kacau. Pikeun ngahemat waktos anjeun, kuring ngawitan unggal bab ku bubuka "Naon Kuring Diajar", nu summarizes hakekat bab dina hiji atawa dua kalimat.

“Témbongkeun solusina!” Upami anjeun ngan ukur hoyong ningali ti mana kuring asalna, teras angkat ka bab "Janten Langkung Inventif," tapi kuring pikir éta langkung narik sareng mangpaat pikeun maca ngeunaan kagagalan.

Kuring nembe ditugaskeun pikeun nyetél prosés pikeun ngolah sajumlah ageung sekuen DNA atah (téhnisna chip SNP). Kabutuhan éta gancang ménta data ngeunaan lokasi genetik dibikeun (disebut SNP) pikeun modeling saterusna sarta tugas séjén. Nganggo R sareng AWK, kuring tiasa ngabersihan sareng ngatur data sacara alami, ngagancangkeun pamrosésan pamundut. Ieu henteu gampang pikeun kuring sareng peryogi seueur iterasi. Tulisan ieu bakal ngabantosan anjeun ngahindarkeun sababaraha kasalahan kuring sareng nunjukkeun ka anjeun naon anu kuring réngsé.

Kahiji, sababaraha katerangan bubuka.

data

Puseur ngolah inpormasi genetik universitas kami nyayogikeun kami data dina bentuk TSV 25 TB. Kuring nampi aranjeunna dibagi kana 5 bungkusan anu dikomprés Gzip, masing-masing ngandung 240 file opat gigabyte. Unggal baris ngandung data pikeun hiji SNP ti hiji individu. Dina total, data dina ~ 2,5 juta SNPs na ~ 60 sarébu jalma anu dikirimkeun. Salian inpormasi SNP, file ngandung seueur kolom sareng nomer anu ngagambarkeun sababaraha ciri, sapertos inténsitas maca, frékuénsi alél anu béda, jsb. Dina total aya ngeunaan 30 kolom kalawan nilai unik.

tujuan

Sapertos proyék manajemén data, anu paling penting nyaéta pikeun nangtoskeun kumaha data bakal dianggo. Dina hal ieu urang lolobana bakal milih model na workflows pikeun SNP dumasar kana SNP. Hartina, urang ngan butuh data dina hiji SNP dina hiji waktu. Kuring kungsi diajar kumaha carana nimba sagala rékaman pakait sareng salah sahiji 2,5 juta SNP sakumaha gampang, gancang tur murah sabisa.

Kumaha teu ngalakukeun ieu

Pikeun cutatan klise cocog:

Kuring henteu gagal sarébu kali, kuring nembé mendakan sarébu cara pikeun ngahindarkeun parsing sakumpulan data dina format anu ramah-query.

Usaha munggaran

Naon anu kuring diajar: Teu aya cara anu murah pikeun nga-parse 25 TB sakaligus.

Saatos nyandak kursus "Metode Advanced pikeun Ngolah Data Big" di Vanderbilt University, kuring yakin yén trik éta aya dina kantong. Ieu meureun bakal butuh hiji atawa dua jam pikeun nyetél server Hive pikeun ngajalankeun ngaliwatan sakabéh data sarta ngalaporkeun hasilna. Kusabab data kami disimpen dina AWS S3, kuring nganggo jasa éta pundah, nu ngidinan Anjeun pikeun nerapkeun queries Hive SQL kana data S3. Anjeun teu perlu nyetél / ngangkat hiji klaster Hive, jeung anjeun ogé mayar ngan pikeun data nu Anjeun keur pilari.

Saatos kuring nunjukkeun Athena data sareng formatna, kuring ngajalankeun sababaraha tés kalayan patarosan sapertos kieu:

select * from intensityData limit 10;

Sareng gancang nampi hasil anu terstruktur. Siap.

Dugi ka urang nyobian nganggo data dina padamelan urang ...

Kuring dipenta pikeun narik kaluar kabeh informasi SNP pikeun nguji model on. Kuring ngajalankeun patarosan:


select * from intensityData 
where snp = 'rs123456';

... sarta mimiti antosan. Saatos dalapan menit sareng langkung ti 4 TB data anu dipénta, kuring nampi hasilna. Athena ngecas ku volume data kapanggih, $5 per terabyte. Janten pamundut tunggal ieu hargana $ 20 sareng dalapan menit ngantosan. Pikeun ngajalankeun modél dina sadaya data, urang kedah ngantosan 38 taun sareng mayar $ 50 juta. Jelas, ieu henteu cocog pikeun urang.

Éta kedah nganggo Parquet ...

Naon anu kuring diajar: Kudu ati kalawan ukuran file Parquet anjeun sarta organisasi maranéhna.

Kuring mimiti nyoba ngalereskeun kaayaan ku ngarobah sakabeh TSVs kana Parquet file. Éta merenah pikeun gawé bareng set data badag sabab informasi dina eta disimpen dina bentuk columnar: unggal kolom perenahna di mémori / bagean disk sorangan, kontras jeung file téks, nu baris ngandung elemen unggal kolom. Tur upami Anjeun salah kudu manggihan hal, teras baca kolom diperlukeun. Salaku tambahan, unggal file nyimpen sauntuyan nilai dina kolom, janten upami nilai anu anjeun milarian henteu aya dina rentang kolom, Spark moal miceunan waktos nyeken sadaya file.

Kuring ngajalankeun tugas basajan Gelas Kolot pikeun ngarobih TSV kami ka Parquet sareng ngahapus file énggal kana Athena. Butuh waktu ngeunaan 5 jam. Tapi lamun kuring lumpat pamundut nu, Butuh ngeunaan jumlah sarua waktu sarta saeutik kirang duit pikeun ngalengkepan. Kanyataan yén Spark, nyobian ngaoptimalkeun tugas, kantun unpacked hiji TSV chunk teras nahan eta dina chunk Parquet sorangan. Sarta alatan unggal chunk éta cukup badag pikeun nahan sakabéh rékaman loba jalma, unggal file ngandung sakabéh SNPs, jadi Spark kedah muka sagala file pikeun nimba informasi eta diperlukeun.

Narikna, standar Parquet urang (jeung dianjurkeun) tipe komprési, snappy, teu splittable. Ku alatan éta, unggal pelaksana macét dina tugas ngabongkar sareng ngaunduh set data 3,5 GB lengkep.

Parsing 25TB nganggo AWK sareng R

Hayu urang ngartos masalah

Naon anu kuring diajar: Asihan hese, utamana lamun data disebarkeun.

Ieu seemed kuring nu ayeuna mah ngartos hakekat masalah. Kuring ngan ukur kedah nyortir data ku kolom SNP, sanés ku jalma. Lajeng sababaraha SNPs bakal disimpen dina chunk data misah, lajeng Parquet urang "pinter" fungsi "muka ngan lamun nilaina aya dina rentang" bakal nembongkeun diri dina sakabéh kamulyaan na. Hanjakal, nyortir ngaliwatan milyaran baris sumebar di sakuliah klaster kabukti tugas hésé.

AWS pasti henteu hoyong ngaluarkeun ngabalikeun duit kusabab alesan "Kuring murid anu kacau". Saatos kuring lumpat asihan dina Amazon Glue, éta ngajalankeun 2 dinten sareng nabrak.

Kumaha upami ngabagi?

Naon anu kuring diajar: Partitions dina Spark kudu saimbang.

Teras kuring mendakan ide pikeun ngabagi data dina kromosom. Aya 23 di antarana (sareng sababaraha deui upami anjeun tumut kana akun DNA mitokondria sareng daérah anu henteu dipetakan).
Ieu bakal ngidinan Anjeun pikeun ngabagi data kana sakumpulan leutik. Upami anjeun nambihan ngan hiji garis kana fungsi ékspor Spark dina naskah Lem partition_by = "chr", mangka data kudu dibagi kana ember.

Parsing 25TB nganggo AWK sareng R
Génom diwangun ku sababaraha fragmen anu disebut kromosom.

Hanjakal, teu hasil. Kromosom boga ukuran béda, nu hartina jumlah informasi béda. Ieu ngandung harti yén tugas anu dikirimkeun ku Spark ka pagawé henteu saimbang sareng réngsé lalaunan kusabab sababaraha titik réngsé awal sareng dianggurkeun. Sanajan kitu, tugas geus réngsé. Tapi nalika naroskeun hiji SNP, henteu saimbangna deui nyababkeun masalah. Biaya ngolah SNP dina kromosom anu langkung ageung (nyaéta, dimana urang badé kéngingkeun data) ngan turun ku kira-kira faktor 10. Loba, tapi teu cukup.

Kumaha upami urang ngabagi kana bagian anu langkung alit?

Naon anu kuring diajar: Pernah nyoba ngalakukeun 2,5 juta partitions pisan.

Kuring mutuskeun pikeun balik kaluar sarta ngabagi unggal SNP. Ieu ensured yén partitions éta ukuran sarua. ETA IAGA JAHAT. I dipaké lem sarta ditambahkeun hiji garis polos partition_by = 'snp'. Tugas dimimitian tur mimitian ngajalankeun. Poé saterusna kuring dipariksa sarta nempo yén aya kénéh nanaon ditulis ka S3, jadi kuring maéhan tugas. Sigana mah Glue nyerat file perantara ka lokasi anu disumputkeun di S3, seueur file, panginten sababaraha juta. Hasilna, kasalahan kuring hargana langkung ti sarébu dolar sareng henteu nyenangkeun mentor kuring.

Ngabagi + asihan

Naon anu kuring diajar: Asihan masih hese, sakumaha tuning Spark.

Usaha terakhir kuring ngabagi ngalibatkeun kuring ngabagi kromosom teras nyortir unggal partisi. Dina tiori, ieu bakal nyepetkeun unggal query sabab data SNP nu dipikahoyong kedah aya dina sababaraha sakumpulan Parquet dina rentang nu tangtu. Hanjakal, asihan malah partitioned data tétéla jadi tugas hésé. Hasilna, kuring ngalih ka EMR pikeun klaster khusus sareng nganggo dalapan instansi anu kuat (C5.4xl) sareng Sparklyr pikeun nyiptakeun alur kerja anu langkung fleksibel ...

# Sparklyr snippet to partition by chr and sort w/in partition
# Join the raw data with the snp bins
raw_data
  group_by(chr) %>%
  arrange(Position) %>% 
  Spark_write_Parquet(
    path = DUMP_LOC,
    mode = 'overwrite',
    partition_by = c('chr')
  )

... kumaha oge, tugas masih teu réngsé. Kuring ngonpigurasikeunana ku sababaraha cara: ningkatkeun alokasi mémori pikeun unggal pelaksana query, ngagunakeun titik kalayan jumlah mémori anu ageung, ngagunakeun variabel siaran (variabel siaran), tapi unggal waktos ieu janten satengah ukuran, sareng laun-laun pelaksana dimimitian. gagal nepi ka sagalana eureun.

Abdi janten langkung kreatif

Naon anu kuring diajar: Kadang data husus merlukeun solusi husus.

Unggal SNP boga nilai posisi. Ieu angka nu pakait jeung jumlah basa sapanjang kromosom na. Ieu mangrupikeun cara anu saé sareng alami pikeun ngatur data urang. Mimitina kuring hayang ngabagi dumasar wewengkon unggal kromosom. Contona, posisi 1 - 2000, 2001 - 4000, jsb. Tapi masalahna nyaeta SNP teu disebarkeun merata sakuliah kromosom, sahingga ukuran grup bakal greatly rupa-rupa.

Parsing 25TB nganggo AWK sareng R

Hasilna, kuring sumping ka ngarecah posisi kana kategori (pangkat). Ngagunakeun data geus diundeur, abdi ngajalankeun pamundut pikeun ménta daptar SNPs unik, posisi na kromosom maranéhna. Teras kuring nyortir data dina unggal kromosom sareng ngumpulkeun SNP kana grup (bin) tina ukuran anu ditangtukeun. Hayu urang nyebutkeun 1000 SNPs unggal. Ieu masihan kuring hubungan SNP-to-group-per-kromosom.

Tungtungna, kuring nyieun grup (bin) 75 SNPs, alesan bakal dipedar di handap.

snp_to_bin <- unique_snps %>% 
  group_by(chr) %>% 
  arrange(position) %>% 
  mutate(
    rank = 1:n()
    bin = floor(rank/snps_per_bin)
  ) %>% 
  ungroup()

Cobaan heula sareng Spark

Naon anu kuring diajar: Spark aggregation gancang, tapi partisi masih mahal.

Abdi hoyong maca pigura data leutik ieu (2,5 juta baris) kana Spark, ngagabungkeun sareng data atah, teras partisi ku kolom anu nembé ditambah. bin.


# Join the raw data with the snp bins
data_w_bin <- raw_data %>%
  left_join(sdf_broadcast(snp_to_bin), by ='snp_name') %>%
  group_by(chr_bin) %>%
  arrange(Position) %>% 
  Spark_write_Parquet(
    path = DUMP_LOC,
    mode = 'overwrite',
    partition_by = c('chr_bin')
  )

Kuring dipaké sdf_broadcast(), jadi Spark terang yén éta kedah ngirim pigura data ka sadaya titik. Ieu mangpaat lamun data leutik dina ukuran sarta diperlukeun pikeun sakabéh tugas. Upami teu kitu, Spark nyobian janten pinter sareng nyebarkeun data upami diperyogikeun, anu tiasa nyababkeun kalem.

Jeung deui, pamanggih kuring teu jalan: tugas digawé pikeun sawatara waktu, réngsé serikat, lajeng, kawas executors dibuka ku partitioning, aranjeunna mimiti gagal.

Nambahan AWK

Naon anu kuring diajar: Tong sare lamun keur diajar dasar. Pasti aya anu parantos ngarengsekeun masalah anjeun dina taun 1980-an.

Nepi ka titik ieu, alesan pikeun sakabéh gagal kuring jeung Spark éta jumble data dina klaster. Panginten kaayaan tiasa ningkat ku pre-treatment. Kuring mutuskeun pikeun nyobaan ngabagi data téks atah kana kolom kromosom kalayan harepan nyayogikeun Spark sareng data "pre-partitioned".

Kuring milarian dina StackOverflow pikeun cara ngabagi ku nilai kolom sareng mendakan jawaban sapertos hébat. Kalayan AWK anjeun tiasa ngabagi file téks ku nilai kolom ku cara nyerat dina naskah tinimbang ngirimkeun hasilna ka stdout.

Kuring nulis skrip Bash pikeun nyobaan. Ngundeur salah sahiji TSVs rangkep, teras unpacked ngagunakeun gzip sarta dikirim ka awk.

gzip -dc path/to/chunk/file.gz |
awk -F 't' 
'{print $1",..."$30">"chunked/"$chr"_chr"$15".csv"}'

Éta digawé!

Ngeusian cores

Naon anu kuring diajar: gnu parallel - éta hal gaib, dulur kudu make eta.

separation ieu rada slow sarta nalika kuring dimimitian htoppikeun pariksa pamakéan a kuat (jeung mahal) conto EC2, tétéla yén kuring ngan ngagunakeun hiji inti na ngeunaan 200 MB memori. Pikeun ngajawab masalah jeung teu leungit loba duit, urang kudu angka kaluar kumaha carana parallelize karya. Untungna, dina buku anu luar biasa Élmu Data di Jalur Komando Kuring kapanggih surah ku Jeron Janssens on parallelization. Ti dinya kuring diajar ngeunaan gnu parallel, métode pisan fléksibel pikeun nerapkeun multithreading di Unix.

Parsing 25TB nganggo AWK sareng R
Nalika kuring ngamimitian partisi ngagunakeun prosés anyar, sagalana éta rupa, tapi masih aya bottleneck a - ngundeur objék S3 kana disk teu pisan gancang jeung teu pinuh parallelized. Pikeun ngalereskeun ieu, kuring ngalakukeun ieu:

  1. Kuring manggihan yén kasebut nyaéta dimungkinkeun pikeun nerapkeun tahap download S3 langsung dina pipa nu, lengkep ngaleungitkeun gudang panengah dina disk. Ieu ngandung harti kuring bisa nyingkahan nulis data atah kana disk jeung make malah leuwih leutik, sarta ku kituna leuwih murah, neundeun on AWS.
  2. tim aws configure set default.s3.max_concurrent_requests 50 greatly ngaronjat jumlah threads anu ngagunakeun AWS CLI (sacara standar aya 10).
  3. Kuring switched ka conto EC2 dioptimalkeun pikeun speed jaringan, jeung hurup n dina ngaran. Kuring geus manggihan yén leungitna kakuatan processing lamun ngagunakeun n-instance leuwih ti dibales ku kanaékan speed loading. Kanggo sabagéan ageung tugas kuring nganggo c5n.4xl.
  4. Dirobah gzip dina pigz, Ieu alat gzip nu bisa ngalakukeun hal tiis pikeun parallelize tugas mimitina non-parallelized of decompressing file (ieu mantuan sahenteuna).

# Let S3 use as many threads as it wants
aws configure set default.s3.max_concurrent_requests 50

for chunk_file in $(aws s3 ls $DATA_LOC | awk '{print $4}' | grep 'chr'$DESIRED_CHR'.csv') ; do

        aws s3 cp s3://$batch_loc$chunk_file - |
        pigz -dc |
        parallel --block 100M --pipe  
        "awk -F 't' '{print $1",..."$30">"chunked/{#}_chr"$15".csv"}'"

       # Combine all the parallel process chunks to single files
        ls chunked/ |
        cut -d '_' -f 2 |
        sort -u |
        parallel 'cat chunked/*_{} | sort -k5 -n -S 80% -t, | aws s3 cp - '$s3_dest'/batch_'$batch_num'_{}'
        
         # Clean up intermediate data
       rm chunked/*
done

Léngkah-léngkah ieu digabungkeun saling pikeun ngajantenkeun sadayana gancang pisan. Ku ningkatkeun kecepatan download sareng ngaleungitkeun tulisan disk, kuring ayeuna tiasa ngolah pakét 5 terabyte ngan ukur sababaraha jam.

Tweet ieu kedah disebatkeun 'TSV'. Aduh.

Ngagunakeun data anyar parsed

Naon anu kuring diajar: Spark resep data anu teu dikomprés sareng henteu resep ngagabungkeun partisi.

Ayeuna data éta dina S3 dina unpacked (baca: dibagikeun) jeung format semi-diatur, sarta kuring bisa balik deui ka Spark. A reuwas ditunggu kuring: Kuring deui gagal pikeun ngahontal naon kuring hayang! Hésé pisan pikeun nyarioskeun Spark persis kumaha datana dibagi. Sareng nalika kuring ngalakukeun ieu, tétéla seueur teuing partisi (95 rébu), sareng nalika kuring dianggo coalesce ngurangan jumlah maranéhna pikeun wates lumrah, ieu ancur partitioning kuring. Kuring yakin ieu tiasa dilereskeun, tapi saatos sababaraha dinten milarian kuring henteu mendakan solusi. Kuring ahirna rengse sagala pancén di Spark, sanajan butuh bari jeung file Parquet pamisah kuring teu leutik pisan (~ 200 KB). Sanajan kitu, data éta dimana diperlukeun.

Parsing 25TB nganggo AWK sareng R
Leutik teuing jeung henteu rata, éndah!

Nguji patarosan Spark lokal

Naon anu kuring diajar: Spark boga teuing overhead nalika ngarengsekeun masalah basajan.

Ku ngundeur data dina format pinter, abdi tiasa nguji speed. Nyetél hiji Aksara Sunda pikeun ngajalankeun server Spark lokal, lajeng dimuat pigura data Spark ti gudang grup Parquet dieusian (bin). Kuring nyoba ngamuat sadaya data tapi teu bisa Sparklyr ngakuan partisi.

sc <- Spark_connect(master = "local")

desired_snp <- 'rs34771739'

# Start a timer
start_time <- Sys.time()

# Load the desired bin into Spark
intensity_data <- sc %>% 
  Spark_read_Parquet(
    name = 'intensity_data', 
    path = get_snp_location(desired_snp),
    memory = FALSE )

# Subset bin to snp and then collect to local
test_subset <- intensity_data %>% 
  filter(SNP_Name == desired_snp) %>% 
  collect()

print(Sys.time() - start_time)

Palaksanaan nyandak 29,415 detik. Hadé pisan, tapi teu alus teuing pikeun nguji massa nanaon. Salaku tambahan, kuring henteu tiasa nyepetkeun hal-hal ku cache sabab nalika kuring nyobian nga-cache pigura data dina mémori, Spark sok nabrak, sanaos kuring nyayogikeun langkung ti 50 GB mémori kana set data anu beuratna kirang ti 15.

Balik deui ka AWK

Naon anu kuring diajar: Associative arrays di AWK pisan efisien.

Kuring sadar yen kuring bisa ngahontal speeds luhur. Kuring inget yen dina éndah AWK tutorial ku Bruce Barnett Kuring maca ngeunaan fitur keren anu disebut "arrays associative" Intina, ieu mangrupikeun pasangan konci-nilai, anu kusabab sababaraha alesan disebut béda dina AWK, sareng ku kituna kuring henteu mikirkeun aranjeunna. Roman Cheplyaka recalled yén istilah "arrays asosiatif" jauh leuwih kolot ti istilah "pasangan konci-nilai". Sanajan anjeun milarian konci-nilai dina Google Ngram, Anjeun moal ningali istilah ieu aya, tapi anjeun bakal manggihan arrays associative! Salaku tambahan, "pasangan konci-nilai" paling sering dikaitkeun sareng pangkalan data, janten langkung raos dibandingkeun sareng hashmap. Kuring sadar yen kuring bisa make ieu arrays associative kaitkeun SNPs abdi sareng tabel bin na data atah tanpa ngagunakeun Spark.

Jang ngalampahkeun ieu, dina skrip AWK I dipaké blok BEGIN. Ieu sapotong kode anu dieksekusi saméméh baris kahiji data dikirimkeun ka awak utama naskah.

join_data.awk
BEGIN {
  FS=",";
  batch_num=substr(chunk,7,1);
  chunk_id=substr(chunk,15,2);
  while(getline < "snp_to_bin.csv") {bin[$1] = $2}
}
{
  print $0 > "chunked/chr_"chr"_bin_"bin[$1]"_"batch_num"_"chunk_id".csv"
}

regu while(getline...) dimuat sadaya baris ti grup CSV (bin), set kolom kahiji (ngaran SNP) salaku konci pikeun arrays associative bin jeung nilai kadua (kelompok) salaku nilai. Lajeng di blok { }, anu dieksekusi dina sadaya jalur file utama, unggal baris dikirim ka file kaluaran, anu nampi nami unik gumantung kana grupna (bin): ..._bin_"bin[$1]"_....

Variabel batch_num и chunk_id loyog data disadiakeun ku pipa, Ngahindarkeun hiji kaayaan lomba, sarta unggal palaksanaan thread ngajalankeun parallel, nulis kana file unik sorangan.

Kusabab kuring sumebar kabeh data atah kana polder on kromosom ditinggalkeun leuwih ti percobaan kuring saméméhna mibanda AWK, ayeuna kuring bisa nulis Aksara Bash sejen pikeun ngolah hiji kromosom dina hiji waktu sarta ngirim data deeper partitioned mun S3.

DESIRED_CHR='13'

# Download chromosome data from s3 and split into bins
aws s3 ls $DATA_LOC |
awk '{print $4}' |
grep 'chr'$DESIRED_CHR'.csv' |
parallel "echo 'reading {}'; aws s3 cp "$DATA_LOC"{} - | awk -v chr=""$DESIRED_CHR"" -v chunk="{}" -f split_on_chr_bin.awk"

# Combine all the parallel process chunks to single files and upload to rds using R
ls chunked/ |
cut -d '_' -f 4 |
sort -u |
parallel "echo 'zipping bin {}'; cat chunked/*_bin_{}_*.csv | ./upload_as_rds.R '$S3_DEST'/chr_'$DESIRED_CHR'_bin_{}.rds"
rm chunked/*

Skripna aya dua bagian parallel.

Dina bagian kahiji, data dibaca tina sadaya file anu ngandung inpormasi ngeunaan kromosom anu dipikahoyong, teras data ieu disebarkeun kana benang, anu nyebarkeun file kana grup anu cocog (bin). Pikeun ngahindarkeun kaayaan balapan nalika sababaraha benang nyerat kana file anu sami, AWK ngalangkungan nami file pikeun nyerat data ka tempat anu béda, f.eks. chr_10_bin_52_batch_2_aa.csv. Hasilna, loba file leutik dijieun dina disk (pikeun ieu kuring dipaké volume terabyte EBS).

Conveyor ti bagian kadua parallel ngaliwatan grup (bin) jeung ngagabungkeun file individu maranéhanana kana CSV umum c catlajeng ngirim aranjeunna pikeun ékspor.

Panyiaran dina basa Sunda?

Naon anu kuring diajar: Anjeun tiasa ngahubungan stdin и stdout ti hiji Aksara Sunda, sarta ku kituna ngagunakeun eta dina pipa nu.

Anjeun panginten tiasa perhatikeun garis ieu dina skrip Bash anjeun: ...cat chunked/*_bin_{}_*.csv | ./upload_as_rds.R.... Éta narjamahkeun sadaya file grup anu dihijikeun (bin) kana aksara Sunda di handap. {} mangrupa téhnik husus parallel, anu nyelapkeun data naon waé anu dikirimkeun ka aliran anu ditangtukeun langsung kana paréntahna sorangan. Pilihan {#} nyadiakeun ID thread unik, jeung {%} ngagambarkeun jumlah slot pakasaban (diulang, tapi pernah sakaligus). Daptar sadaya pilihan tiasa dipendakan dina dokuméntasi.

#!/usr/bin/env Rscript
library(readr)
library(aws.s3)

# Read first command line argument
data_destination <- commandArgs(trailingOnly = TRUE)[1]

data_cols <- list(SNP_Name = 'c', ...)

s3saveRDS(
  read_csv(
        file("stdin"), 
        col_names = names(data_cols),
        col_types = data_cols 
    ),
  object = data_destination
)

Nalika variabel file("stdin") dikirimkeun ka readr::read_csv, data nu ditarjamahkeun kana aksara Sunda dimuat kana pigura, nu saterusna dina wangun .rds-file ngagunakeun aws.s3 ditulis langsung ka S3.

RDS mangrupa hal kawas versi junior of Parquet, tanpa frills gudang spiker.

Saatos réngsé naskah Bash kuring ngagaduhan bungkusan .rds-file lokasina di S3, nu diwenangkeun kuring ngagunakeun komprési efisien sarta diwangun-di jenis.

Sanajan pamakéan rem R, sagalana digawé gancang pisan. Teu anéh, bagéan basa Sunda anu maca jeung nulis data téh kacida dioptimalkeunana. Saatos nguji dina hiji kromosom sedeng-ukuran, pakasaban réngsé dina conto C5n.4xl dina ngeunaan dua jam.

S3 Watesan

Naon anu kuring diajar: Hatur nuhun kana palaksanaan jalur pinter, S3 tiasa ngadamel loba file.

Kuring hariwang naha S3 bakal tiasa ngadamel seueur file anu ditransferkeun ka dinya. Kuring bisa nyieun ngaran file make akal pikiran, tapi kumaha S3 bakal néangan aranjeunna?

Parsing 25TB nganggo AWK sareng R
Polder di S3 ngan pikeun acara, kanyataanna sistem teu kabetot dina simbol /. Ti kaca FAQ S3.

Nembongan yen S3 ngagambarkeun jalur ka file tinangtu salaku konci basajan dina nurun tina tabel hash atawa database dumasar-dokumen. LIPI tiasa dianggap salaku méja, sareng file tiasa dianggap rékaman dina méja éta.

Kusabab kagancangan sareng efisiensi penting pikeun ngahasilkeun kauntungan di Amazon, henteu heran yén sistem jalur konci-sakumaha-file-jalur ieu dioptimalkeun. Kuring diusahakeun neangan kasaimbangan a: ku kituna kuring teu kudu nyieun loba requests meunang, tapi nu requests anu dieksekusi gancang. Tétéla éta pangalusna nyieun ngeunaan 20 sarébu file bin. Jigana lamun urang terus ngaoptimalkeun, urang bisa ngahontal kanaékan speed (Contona, nyieun ember husus ngan pikeun data, sahingga ngurangan ukuran tabel lookup). Tapi teu aya waktos atanapi artos pikeun percobaan salajengna.

Kumaha upami kasaluyuan cross?

Anu Kuring Diajar: Anu jadi sabab nomer hiji waktos anu dibuang nyaéta ngaoptimalkeun metode panyimpen anjeun sateuacana.

Dina titik ieu, penting pisan pikeun naroskeun ka diri anjeun: "Naha nganggo format file proprietary?" Alesanna aya dina laju ngamuat (file CSV gzipped nyandak 7 kali langkung lami pikeun dimuat) sareng kasaluyuan sareng alur kerja urang. Kuring bisa nimbangkeun balik lamun Sunda bisa kalayan gampang ngamuat Parquet (atanapi Panah) file tanpa beban Spark. Sarerea di lab urang ngagunakeun R, sarta lamun kuring kudu ngarobah data kana format sejen, Kuring masih boga data téks aslina, jadi kuring ngan bisa ngajalankeun pipa deui.

Divisi gawé

Naon anu kuring diajar: Ulah coba ngaoptimalkeun jobs sacara manual, hayu komputer ngalakukeun eta.

Kuring geus debugged workflow dina hiji kromosom, ayeuna kuring kudu ngolah sakabeh data lianna.
Abdi hoyong ngangkat sababaraha instansi EC2 pikeun konvérsi, tapi dina waktos anu sami kuring sieun kéngingkeun beban anu henteu saimbang dina padamelan pangolahan anu béda (sapertos Spark ngalaman partisi henteu saimbang). Salaku tambahan, kuring henteu resep ngangkat hiji conto per kromosom, sabab pikeun akun AWS aya wates standar 10 instansi.

Teras kuring mutuskeun nyerat naskah dina basa Sunda pikeun ngaoptimalkeun padamelan ngolah.

Kahiji, kuring nanya ka S3 keur ngitung sabaraha spasi gudang unggal kromosom nempatan.

library(aws.s3)
library(tidyverse)

chr_sizes <- get_bucket_df(
  bucket = '...', prefix = '...', max = Inf
) %>% 
  mutate(Size = as.numeric(Size)) %>% 
  filter(Size != 0) %>% 
  mutate(
    # Extract chromosome from the file name 
    chr = str_extract(Key, 'chr.{1,4}.csv') %>%
             str_remove_all('chr|.csv')
  ) %>% 
  group_by(chr) %>% 
  summarise(total_size = sum(Size)/1e+9) # Divide to get value in GB



# A tibble: 27 x 2
   chr   total_size
   <chr>      <dbl>
 1 0           163.
 2 1           967.
 3 10          541.
 4 11          611.
 5 12          542.
 6 13          364.
 7 14          375.
 8 15          372.
 9 16          434.
10 17          443.
# … with 17 more rows

Teras kuring nyerat fungsi anu nyandak ukuran total, ngacak urutan kromosom, ngabagi kana grup. num_jobs sareng nyarioskeun ka anjeun kumaha bédana ukuran sadaya padamelan ngolah.

num_jobs <- 7
# How big would each job be if perfectly split?
job_size <- sum(chr_sizes$total_size)/7

shuffle_job <- function(i){
  chr_sizes %>%
    sample_frac() %>% 
    mutate(
      cum_size = cumsum(total_size),
      job_num = ceiling(cum_size/job_size)
    ) %>% 
    group_by(job_num) %>% 
    summarise(
      job_chrs = paste(chr, collapse = ','),
      total_job_size = sum(total_size)
    ) %>% 
    mutate(sd = sd(total_job_size)) %>% 
    nest(-sd)
}

shuffle_job(1)



# A tibble: 1 x 2
     sd data            
  <dbl> <list>          
1  153. <tibble [7 × 3]>

Saterusna kuring lumpat ngaliwatan sarébu shuffles maké purrr tur milih nu pangalusna.

1:1000 %>% 
  map_df(shuffle_job) %>% 
  filter(sd == min(sd)) %>% 
  pull(data) %>% 
  pluck(1)

Ku kituna kuring réngsé nepi ka sakumpulan tugas anu ukuranana pisan sarupa. Teras sadayana anu tinggaleun nyaéta mungkus skrip Bash sateuacana dina loop anu ageung for. optimasi ieu nyandak ngeunaan 10 menit nulis. Sareng ieu langkung seueur tibatan anu kuring bakal nyéépkeun pikeun nyiptakeun tugas sacara manual upami aranjeunna henteu saimbang. Ku alatan éta, kuring nyangka yén kuring leres kalayan optimasi awal ieu.

for DESIRED_CHR in "16" "9" "7" "21" "MT"
do
# Code for processing a single chromosome
fi

Dina tungtungna kuring nambahan paréntah shutdown:

sudo shutdown -h now

... jeung sagalana digawé kaluar! Ngagunakeun AWS CLI, abdi diangkat instansi ngagunakeun pilihan user_data masihan aranjeunna skrip Bash tina tugasna pikeun ngolah. Aranjeunna ngajalankeun sareng mareuman sacara otomatis, janten kuring henteu mayar kakuatan pamrosésan tambahan.

aws ec2 run-instances ...
--tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=<<job_name>>}]" 
--user-data file://<<job_script_loc>>

Hayu pak!

Naon anu kuring diajar: API kudu basajan demi betah tur kalenturan pamakéan.

Tungtungna kuring ngagaduhan data dina tempat sareng bentuk anu leres. Sadaya anu tetep nyaéta pikeun nyederhanakeun prosés ngagunakeun data sabisa-bisa pikeun ngagampangkeun kolega kuring. Kuring hayang nyieun API basajan pikeun nyieun requests. Lamun dina mangsa nu bakal datang kuring mutuskeun pikeun pindah ti .rds mun file Parquet, lajeng ieu kudu jadi masalah keur kuring, teu keur kolega kuring. Pikeun ieu kuring mutuskeun hiji pakét R internal.

Ngawangun sareng ngadokumentasikeun pakét anu saderhana pisan anu ngan ukur sababaraha fungsi aksés data anu diatur dina hiji fungsi get_snp. Kuring ogé nyieun hiji ramatloka pikeun kolega kuring pkgdown, ngarah bisa kalayan gampang ningali conto jeung dokuméntasi.

Parsing 25TB nganggo AWK sareng R

Caching pinter

Naon anu kuring diajar: Lamun data anjeun disusun ogé, cache bakal gampang!

Kusabab salah sahiji workflows utama dilarapkeun model analisis sarua jeung pakét SNP, Kuring mutuskeun pikeun ngagunakeun binning kana kaunggulan kuring. Nalika ngirimkeun data via SNP, sadaya inpormasi ti grup (bin) digantelkeun kana objék anu dipulangkeun. Hartina, queries heubeul bisa (dina tiori) nyepetkeun ngolah queries anyar.

# Part of get_snp()
...
  # Test if our current snp data has the desired snp.
  already_have_snp <- desired_snp %in% prev_snp_results$snps_in_bin

  if(!already_have_snp){
    # Grab info on the bin of the desired snp
    snp_results <- get_snp_bin(desired_snp)

    # Download the snp's bin data
    snp_results$bin_data <- aws.s3::s3readRDS(object = snp_results$data_loc)
  } else {
    # The previous snp data contained the right bin so just use it
    snp_results <- prev_snp_results
  }
...

Nalika ngawangun pakét, kuring ngajalankeun seueur tolok ukur pikeun ngabandingkeun kagancangan nalika nganggo metode anu béda. Kuring nyarankeun teu maranéh ngalalaworakeun kana ieu, sabab kadang hasilna teu kaduga. Salaku conto, dplyr::filter éta leuwih gancang ti néwak barisan maké nyaring dumasar indexing, sarta retrieving hiji kolom tina pigura data disaring éta leuwih gancang ti ngagunakeun indexing sintaksis.

Punten dicatet yén obyék prev_snp_results ngandung konci snps_in_bin. Ieu mangrupa Asép Sunandar Sunarya ti sakabéh SNPs unik dina grup (bin), ngamungkinkeun Anjeun pikeun gancang pariksa naha anjeun geus boga data ti query saméméhna. Éta ogé ngagampangkeun pikeun ngaliwat sadaya SNP dina grup (bin) kalayan kode ieu:

# Get bin-mates
snps_in_bin <- my_snp_results$snps_in_bin

for(current_snp in snps_in_bin){
  my_snp_results <- get_snp(current_snp, my_snp_results)
  # Do something with results 
}

Hasil

Ayeuna urang tiasa (sareng parantos serius) ngajalankeun modél sareng skenario anu saacanna teu tiasa diaksés ku urang. Anu pangsaéna nyaéta kolega lab kuring henteu kedah mikirkeun komplikasi naon waé. Éta ngan ukur gaduh fungsi anu tiasa dianggo.

Sareng sanaos pakét nyéépkeun detilna, kuring nyobian ngajantenkeun format data saderhana supados aranjeunna tiasa terang upami kuring ujug-ujug ngaleungit énjing ...

Laju geus ngaronjat noticeably. Urang biasana nyeken fragmen génom anu penting sacara fungsional. Saméméhna, urang teu bisa ngalakukeun ieu (tétéla jadi mahal teuing), tapi ayeuna, hatur nuhun kana grup (bin) struktur jeung cache, pamundut hiji SNP nyokot rata-rata kirang ti 0,1 detik, sarta pamakéan data kitu. low yén waragad pikeun S3 téh kacang.

kacindekan

Tulisan ieu sanés pituduh. Solusina janten individu, sareng ampir pasti henteu optimal. Sabalikna, éta mangrupikeun perjalanan perjalanan. Abdi hoyong batur ngartos yen kaputusan misalna teu némbongan pinuh kabentuk dina sirah, aranjeunna hasil tina trial and error. Ogé, upami anjeun milarian élmuwan data, émut yén ngagunakeun alat-alat ieu sacara efektif ngabutuhkeun pangalaman, sareng pangalaman butuh artos. Abdi bagja yén kuring ngagaduhan artos pikeun mayar, tapi seueur anu sanés anu tiasa ngalakukeun padamelan anu sami langkung saé tibatan kuring moal pernah ngagaduhan kasempetan kusabab kakurangan artos pikeun nyobian.

parabot data badag anu serbaguna. Upami anjeun gaduh waktos, anjeun ampir pasti tiasa nyerat solusi anu langkung gancang ngagunakeun téknik beberesih, neundeun, sareng ékstraksi data anu pinter. Pamustunganana datang ka analisis biaya-manfaat.

Anu kuring diajar:

  • teu aya jalan murah pikeun parse 25 TB sakaligus;
  • ati-ati ku ukuran file Parquet anjeun sareng organisasina;
  • Partisi dina Spark kedah saimbang;
  • Sacara umum, pernah nyoba nyieun 2,5 juta partitions;
  • Asihan masih hese, sakumaha anu nyetél Spark;
  • kadang data husus merlukeun solusi husus;
  • Spark aggregation gancang, tapi partisi masih mahal;
  • entong bobo nalika aranjeunna ngajarkeun anjeun dasar-dasar, sigana aya anu parantos ngarengsekeun masalah anjeun dina taun 1980-an;
  • gnu parallel - Ieu hal gaib, dulur kudu make eta;
  • Spark resep data anu teu dikomprés sareng henteu resep ngagabungkeun partisi;
  • Spark boga teuing overhead nalika ngarengsekeun masalah basajan;
  • Array asosiatif AWK pisan éfisién;
  • anjeun tiasa ngahubungan stdin и stdout ti hiji Aksara Sunda, sarta ku kituna ngagunakeun eta dina pipa;
  • Hatur nuhun kana palaksanaan jalur pinter, S3 tiasa ngolah seueur file;
  • Alesan utama pikeun wasting waktos prematurely optimizing metoda gudang Anjeun;
  • ulah coba ngaoptimalkeun tugas sacara manual, hayu komputer ngalakukeun eta;
  • API kudu basajan demi betah tur kalenturan pamakéan;
  • Upami data anjeun parantos disiapkeun, cache bakal gampang!

sumber: www.habr.com

Tambahkeun komentar