Таҳлили 25TB бо истифода аз AWK ва R

Таҳлили 25TB бо истифода аз AWK ва R
Чӣ тавр ин мақоларо хондан мумкин аст: Ман узр мепурсам, ки матн хеле дароз ва бесарусомон аст. Барои сарфаи вақти шумо, ман ҳар як бобро бо муқаддимаи "Чӣ омӯхтам" оғоз мекунам, ки моҳияти бобро дар як ё ду ҷумла ҷамъбаст мекунад.

"Танҳо роҳи ҳалро ба ман нишон деҳ!" Агар шумо фақат хоҳед бубинед, ки ман аз куҷо омадаам, пас ба боби "Ихтироъкортар шудан" гузаред, аммо ман фикр мекунам, ки хондан дар бораи нокомӣ ҷолибтар ва муфидтар аст.

Ба наздикӣ ба ман супориш дода шуд, ки раванди коркарди миқдори зиёди пайдарпаии ДНК-и хомро (аз ҷиҳати техникӣ чипи SNP) таъсис диҳам. Зарурати зуд ба даст овардани маълумот дар бораи макони генетикии додашуда (SNP номида мешавад) барои моделсозии минбаъда ва дигар вазифаҳо буд. Бо истифода аз R ва AWK, ман тавонистам маълумотро ба таври табиӣ тоза ва ташкил кунам ва коркарди дархостҳоро хеле суръат бахшам. Ин барои ман осон набуд ва такрори сершуморро талаб мекард. Ин мақола ба шумо кӯмак мекунад, ки аз баъзе хатогиҳои ман канорагирӣ кунед ва ба шумо нишон диҳед, ки ман чӣ кор кардам.

Якум, баъзе шарҳҳои муқаддимавӣ.

маълумот

Маркази коркарди иттилооти генетикии донишгоҳи мо ба мо маълумотро дар шакли TSV 25 TB пешниҳод кард. Ман онҳоро ба 5 баста тақсим кардам, ки аз ҷониби Gzip фишурда шудаанд, ки ҳар яки онҳо тақрибан 240 файли чор гигабайтӣ доштанд. Ҳар як сатр дорои маълумот барои як SNP аз як шахс буд. Дар маҷмӯъ, маълумот дар бораи ~ 2,5 миллион SNP ва ~ 60 ҳазор нафар интиқол дода шуд. Илова ба маълумоти SNP, дар файлҳо сутунҳои сершумор мавҷуданд, ки рақамҳои дорои хусусиятҳои гуногунро инъикос мекунанд, ба монанди шиддати хондан, басомади аллелҳои гуногун ва ғайра. Дар маҷмӯъ тақрибан 30 сутун бо арзишҳои беназир мавҷуд буданд.

Мақсад

Мисли ҳама гуна лоиҳаи идоракунии додаҳо, чизи аз ҳама муҳим муайян кардани он буд, ки маълумот чӣ гуна истифода мешавад. Дар ин маврид мо асосан моделҳо ва ҷараёнҳои корро барои SNP дар асоси SNP интихоб мекунем. Яъне, дар як вақт ба мо танҳо маълумот дар бораи як SNP лозим мешавад. Ман бояд ёд гирам, ки чӣ гуна ҳама сабтҳои марбут ба яке аз 2,5 миллион SNP-ро ба осонӣ, зуд ва арзонтар дастрас кунам.

Чӣ тавр ин корро накунед

Барои иқтибос овардани як клишеи мувофиқ:

Ман ҳазорҳо маротиба ноком нашудам, ман танҳо ҳазорҳо роҳро кашф кардам, ки аз таҳлили як даста маълумот дар формати пурсиш дӯстона канорагирӣ кунам.

Аввал кӯшиш кунед

Ман чӣ омӯхтам: Ягон роҳи арзони таҳлили 25 ТБ дар як вақт вуҷуд надорад.

Ҳангоми дар Донишгоҳи Вандербилт курси "Усулҳои пешрафтаи коркарди маълумоти калон" ман боварӣ доштам, ки ҳилла дар халта аст. Эҳтимол як ё ду соат барои насб кардани сервери Hive барои иҷро кардани тамоми маълумот ва гузориш додани натиҷа лозим аст. Азбаски маълумоти мо дар AWS S3 нигоҳ дошта мешавад, ман аз хидмат истифода кардам Афина, ки ба шумо имкон медиҳад дархостҳои Hive SQL-ро ба додаҳои S3 татбиқ кунед. Ба шумо лозим нест, ки кластери Hive-ро таъсис диҳед/боло кунед ва шумо инчунин танҳо барои маълумоти ҷустуҷӯкардаатон пардохт мекунед.

Пас аз он ки ман маълумот ва формати худро ба Афина нишон додам, ман якчанд санҷишҳоро бо чунин саволҳо гузаронидам:

select * from intensityData limit 10;

Ва ба зудӣ натиҷаҳои хуби сохторӣ гирифтанд. Тайёр.

То он даме, ки мо кӯшиш кардем, ки маълумотро дар кори худ истифода барем...

Аз ман хоҳиш карда шуд, ки ҳама маълумоти SNP-ро барои санҷиши модел берун кунам. Ман дархостро иҷро кардам:


select * from intensityData 
where snp = 'rs123456';

...ва интизор шудан гирифт. Пас аз ҳашт дақиқа ва зиёда аз 4 TB маълумоти дархостшуда, ман натиҷаро гирифтам. Афина аз рӯи ҳаҷми маълумоти ёфтшуда, барои як терабайт $5 ситонида мешавад. Ҳамин тавр, ин дархости ягона 20 доллар ва ҳашт дақиқа интизорӣ арзиш дошт. Барои ба кор даровардани модел дар тамоми маълумот мо бояд 38 сол интизор шавем ва 50 миллион доллар пардохт кунем.. Аён аст, ки ин барои мо мувофиқ набуд.

Паркетро истифода бурдан лозим буд...

Ман чӣ омӯхтам: Аз андозаи файлҳои Паркет ва ташкили онҳо эҳтиёт шавед.

Ман аввал кӯшиш кардам, ки вазъиятро тавассути табдил додани ҳама TSV-ҳо ба ислоҳ кунам Файлҳои паркетӣ. Онҳо барои кор бо маҷмӯи додаҳои калон қулай мебошанд, зеро информатсия дар онҳо дар шакли сутунӣ нигоҳ дошта мешавад: ҳар як сутун дар сегменти хотира/диски худ ҷойгир аст, дар муқоиса бо файлҳои матнӣ, ки сатрҳо унсурҳои ҳар як сутунро дар бар мегиранд. Ва агар ба шумо чизе пайдо кардан лозим бошад, танҳо сутуни заруриро хонед. Илова бар ин, ҳар як файл як қатор арзишҳоро дар сутун нигоҳ медорад, бинобар ин, агар арзише, ки шумо ҷустуҷӯ мекунед, дар диапазони сутун набошад, Spark вақти сканкунии тамоми файлро беҳуда сарф намекунад.

Ман як вазифаи оддӣ иҷро кардам AWS ширеш барои табдил додани TSV-ҳои мо ба Паркет ва файлҳои навро ба Афина партофт. Ин тақрибан 5 соат гирифт. Аммо вақте ки ман дархостро иҷро кардам, барои анҷом додани он тақрибан ҳамон вақт ва каме камтар пул лозим буд. Гап дар он аст, ки Spark, кӯшиш мекунад, ки вазифаро оптимизатсия кунад, танҳо як порчаи TSV-ро кушод ва онро ба порчаи Паркети худ гузошт. Ва азбаски ҳар як порча ба қадри кофӣ калон буд, ки тамоми сабтҳои бисёр одамонро дар бар гирад, ҳар як файл дорои тамоми SNP-ҳо буд, аз ин рӯ Spark маҷбур шуд, ки ҳамаи файлҳоро барои истихроҷи маълумоти зарурӣ кушояд.

Ҷолиб он аст, ки навъи фишурдасозии пешфарз (ва тавсияшаванда)-и Паркет, зуд, тақсимшаванда нест. Аз ин рӯ, ҳар як иҷрокунанда ба вазифаи кушодан ва зеркашии маҷмӯи пурраи 3,5 ГБ часпида буд.

Таҳлили 25TB бо истифода аз AWK ва R

Биёед мушкилотро фаҳмем

Ман чӣ омӯхтам: Ҷудокунӣ душвор аст, хусусан агар маълумот тақсим карда шавад.

Ба назарам чунин менамуд, ки акнун ман мохияти масъаларо фахмидам. Ман танҳо лозим буд, ки маълумотро аз рӯи сутуни SNP ҷудо кунам, на аз рӯи одамон. Он гоҳ якчанд SNP дар як порчаи алоҳидаи додаҳо нигоҳ дошта мешаванд ва он гоҳ функсияи "ақл" -и Паркет "танҳо дар сурати дар диапазон будан кушода" худро бо тамоми шӯҳрати худ нишон медиҳад. Мутаассифона, ҷудо кардани миллиардҳо сатрҳои дар як кластер парокандашуда кори душвор буд.

AWS бешубҳа намехоҳад баргардонидани маблағро бо сабаби "Ман донишҷӯи парешон ҳастам". Пас аз он ки ман дар Amazon Glue ҷудокуниро иҷро кардам, он 2 рӯз кор кард ва суқут кард.

Дар бораи тақсимкунӣ чӣ гуфтан мумкин аст?

Ман чӣ омӯхтам: Қисмҳо дар Spark бояд мутавозин бошанд.

Пас аз он ман идеяи тақсим кардани маълумотро дар хромосомаҳо пайдо кардам. 23-тои онҳо вуҷуд доранд (ва чанде дигар, агар шумо ДНК-и митохондриалӣ ва минтақаҳои хаританашударо ба назар гиред).
Ин ба шумо имкон медиҳад, ки маълумотро ба қисмҳои хурдтар тақсим кунед. Агар шумо ба функсияи содироти Spark дар скрипти Glue танҳо як сатр илова кунед partition_by = "chr", пас маълумот бояд ба сатилҳо тақсим карда шавад.

Таҳлили 25TB бо истифода аз AWK ва R
Геном аз порчаҳои сершумори хромосомаҳо иборат аст.

Мутаассифона, он кор накард. Хромосомаҳо андозаҳои гуногун доранд, ки ин маънои миқдори гуногуни иттилоотро дорад. Ин чунин маъно дорад, ки супоришхое, ки Spark ба коргарон мефиристод, мутаносиб набуданд ва суст ичро мешуданд, зеро баъзе узелхо барвакт ба охир расида, бекор меистоданд. Бо вуҷуди ин, вазифаҳо иҷро шуданд. Аммо ҳангоми дархост кардани як SNP, номутавозунӣ боз мушкилотро ба вуҷуд овард. Арзиши коркарди SNP-ҳо дар хромосомаҳои калонтар (яъне дар он ҷо мо мехоҳем маълумот гирем) танҳо тақрибан 10 маротиба кам шудааст. Бисёр, вале кофӣ нест.

Чӣ мешавад, агар мо онро ба қисмҳои хурдтар тақсим кунем?

Ман чӣ омӯхтам: Ҳеҷ гоҳ кӯшиш накунед, ки 2,5 миллион қисмҳоро иҷро кунед.

Ман қарор додам, ки ҳама чизро тарк кунам ва ҳар як SNP-ро тақсим кунам. Ин кафолат дод, ки қисмҳо андозаи баробар доранд. ИН ИДЕЯИ БАД БУД. Ман ширешро истифода кардам ва хати бегуноҳро илова кардам partition_by = 'snp'. Вазифа сар шуд ва ба ичрои он шуруъ кард. Пас аз як рӯз ман тафтиш кардам ва дидам, ки то ҳол ба S3 чизе навишта нашудааст, бинобар ин ман супоришро куштам. Чунин ба назар мерасад, ки Glue файлҳои фосилавиро ба макони пинҳонӣ дар S3 менавишт, бисёр файлҳо, шояд якчанд миллионҳо. Дар натиҷа, хатои ман зиёда аз ҳазор доллар арзиш дошт ва устодамро шод накард.

Тақсимкунӣ + ҷудокунӣ

Ман чӣ омӯхтам: Ҷудокунӣ ҳоло ҳам мушкил аст, мисли танзими Spark.

Кӯшиши охирини ман барои тақсимкунӣ ба ман тақсим кардани хромосомаҳо ва сипас ҷудо кардани ҳар як қисмро дар бар мегирифт. Дар назария, ин ҳар як дархостро суръат мебахшад, зеро маълумоти дилхоҳи SNP бояд дар доираи якчанд қисмҳои Паркет дар доираи додашуда бошад. Мутаассифона, ба тартиб андохтани ҳатто маълумотҳои тақсимшуда кори душвор гардид. Дар натиҷа, ман барои кластери фармоишӣ ба EMR гузаштам ва ҳашт мисоли пурқувват (C5.4xl) ва Sparklyr-ро барои эҷоди ҷараёни кори чандиртар истифода кардам...

# 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')
  )

...Аммо супориш хануз ичро нашуда буд. Ман онро бо тарзҳои гуногун танзим кардам: тақсимоти хотира барои ҳар як иҷрокунандаи дархост зиёд карда шуд, гиреҳҳои дорои миқдори зиёди хотира истифода мешуданд, тағирёбандаҳои пахши истифодашуда (тағйирёбандаҳои пахш) истифода мешуданд, аммо ҳар дафъа инҳо нимченакҳо буданд ва тадриҷан иҷрокунандагон оғоз карданд. то даме ки ҳама чиз қатъ нашавад, ноком шудан.

Ман бештар эҷодкор мешавам

Ман чӣ омӯхтам: Баъзан маълумоти махсус ҳалли махсусро талаб мекунад.

Ҳар як SNP арзиши мавқеъ дорад. Ин рақамест, ки ба шумораи асосҳо дар баробари хромосомаи он мувофиқ аст. Ин роҳи хуб ва табиии ташкили маълумоти мост. Дар аввал ман мехостам ба минтақаҳои ҳар як хромосома тақсим кунам. Масалан, мавқеъҳои 1 - 2000, 2001 - 4000 ва ғайра. Аммо мушкилот дар он аст, ки SNPҳо дар хромосомаҳо баробар тақсим карда нашудаанд, аз ин рӯ андозаи гурӯҳҳо хеле фарқ мекунанд.

Таҳлили 25TB бо истифода аз AWK ва R

Дар натиҷа, ман ба тақсимоти вазифаҳо ба категорияҳо (рутбаҳо) омадам. Бо истифода аз маълумоти аллакай зеркашида, ман дархост барои гирифтани рӯйхати SNP-ҳои беназир, мавқеъҳо ва хромосомаҳои онҳоро иҷро кардам. Сипас ман маълумотро дар дохили ҳар як хромосома ҷудо кардам ва SNP-ро ба гурӯҳҳо (бин) андозаи додашуда ҷамъоварӣ кардам. Биёед бигӯем, ки ҳар як 1000 SNP. Ин ба ман муносибати SNP-ба-гурӯҳ-ҳар-хромосома дод.

Дар охир, ман гурӯҳҳоро (бин) аз 75 SNP сохтам, сабаб дар зер шарҳ дода мешавад.

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

Аввалан бо Spark кӯшиш кунед

Ман чӣ омӯхтам: Ҷамъоварии шарора зуд аст, аммо тақсимкунӣ ҳанӯз гарон аст.

Ман мехостам, ки ин чаҳорчӯбаи хурди маълумотро (2,5 миллион сатр) дар Spark хонам, онро бо маълумоти хом муттаҳид созам ва сипас онро ба сутуни нав иловашуда тақсим кунам 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')
  )

истифода бурдам sdf_broadcast(), бинобар ин Spark медонад, ки он бояд чаҳорчӯбаи маълумотро ба ҳама гиреҳҳо фиристад. Ин муфид аст, агар маълумот хурд бошад ва барои ҳама вазифаҳо зарур бошад. Дар акси ҳол, Spark мекӯшад оқилона бошад ва маълумотро дар ҳолати зарурӣ паҳн мекунад, ки метавонад боиси сустшавӣ гардад.

Ва боз фикри ман кор на-кард: супоришхо муддате кор карда, иттиходияро ба охир расонданд ва баъд, ба монанди ичрокунан-дагоне, ки бо таксимкунй ба кор андохта шудаанд, ноком шуданд.

Илова кардани AWK

Ман чӣ омӯхтам: Вақте ки ба шумо асосҳои таълим дода мешавад, хоб накунед. Албатта, касе мушкилоти шуморо дар солҳои 1980 ҳал карда буд.

То ин вақт, сабаби ҳама нокомиҳои ман бо Spark ин омехтаи маълумот дар кластер буд. Шояд вазъиятро бо табобати пешакӣ беҳтар кардан мумкин аст. Ман тасмим гирифтам, ки маълумоти матнии хомро ба сутунҳои хромосомаҳо тақсим кунам, бинобар ин ман умедворам, ки Spark-ро бо маълумоти "пеш аз тақсимшуда" таъмин кунам.

Ман дар StackOverflow ҷустуҷӯ кардам, ки чӣ гуна аз рӯи арзишҳои сутун тақсим кардан мумкин аст ва ёфтам чунин ҷавоби олӣ. Бо AWK шумо метавонед файли матниро аз рӯи арзишҳои сутун бо навиштани он дар скрипт тақсим кунед, ба ҷои фиристодани натиҷаҳо ба stdout.

Ман як скрипти Bash навиштам, то онро санҷед. Яке аз TSV-ҳои бастабандишударо зеркашӣ карда, сипас онро бо истифода аз бастабандӣ кушод gzip ва фиристоданд awk.

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

Он кор кард!

Пур кардани ядроҳо

Ман чӣ омӯхтам: gnu parallel — ин чизи сехрнок аст, бояд хама аз он истифода баранд.

Ҷудоӣ хеле суст буд ва вақте ки ман оғоз кардам htopбарои тафтиши истифодаи як мисоли пурқувват (ва гаронбаҳо) EC2, маълум шуд, ки ман танҳо як ядро ​​​​ва тақрибан 200 МБ хотираро истифода мебарам. Барои халли масъала ва аз даст надодани маблаги зиёд ба мо лозим омад, ки корро чй тавр параллел кунем. Хушбахтона, дар як китоби комилан аҷиб Илми маълумот дар хати фармон Ман боби Ҷерон Янсенсро дар бораи параллелизатсия пайдо кардам. Аз он фахмидам gnu parallel, як усули хеле чандир барои татбиқи бисёр риштаҳо дар Unix.

Таҳлили 25TB бо истифода аз AWK ва R
Вақте ки ман тақсимкуниро бо истифода аз раванди нав оғоз кардам, ҳама чиз хуб буд, аммо то ҳол мушкилот вуҷуд дошт - зеркашии объектҳои S3 ба диск он қадар зуд набуд ва пурра параллелизатсия нашудааст. Барои ислоҳ кардани ин, ман ин корро кардам:

  1. Ман фаҳмидам, ки мумкин аст, ки марҳилаи зеркашии S3-ро мустақиман дар лӯла амалӣ карда, нигаҳдории фосилавӣ дар дискро комилан аз байн бурд. Ин маънои онро дорад, ки ман метавонам аз навиштани маълумоти хом ба диск худдорӣ кунам ва нигоҳдории ҳатто хурдтар ва аз ин рӯ арзонтарро дар AWS истифода барам.
  2. даста aws configure set default.s3.max_concurrent_requests 50 шумораи риштаҳоеро, ки AWS CLI истифода мебарад, хеле зиёд кард (бо нобаёнӣ 10 адад вуҷуд дорад).
  3. Ман ба як намунаи EC2, ки барои суръати шабака оптимизатсия шудааст, бо ҳарфи n дар ном гузаштам. Ман фаҳмидам, ки талафоти қудрати коркард ҳангоми истифодаи n-насаҳо бештар аз афзоиши суръати боркунӣ ҷуброн карда мешавад. Барои аксари вазифаҳо ман c5n.4xl истифода кардам.
  4. Тағйир дода шуд gzip ба pigz, ин як абзори gzip аст, ки метавонад корҳои олиҷанобро барои мувозӣ кардани вазифаи дар аввал параллелизатсияшуда кушодани файлҳо анҷом диҳад (ин камтарин кӯмак кард).

# 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

Ин қадамҳо бо ҳамдигар якҷоя карда мешаванд, то ҳама чиз хеле зуд кор кунад. Бо баланд бардоштани суръати зеркашӣ ва аз байн бурдани сабтҳои диск, ман акнун метавонам бастаи 5 терабайтро дар тӯли чанд соат коркард кунам.

Ин твит бояд 'TSV'-ро зикр мекард. Афсус.

Истифодаи маълумоти нав таҳлилшуда

Ман чӣ омӯхтам: Spark маълумоти фишурданашударо дӯст медорад ва якҷоя кардани қисмҳоро дӯст намедорад.

Ҳоло маълумот дар S3 дар формати кушода (хондан: муштарак) ва нимтартиб буд ва ман метавонам дубора ба Spark баргардам. Маро сюрприз интизор буд: боз ба он чизе, ки мехостам ба даст наомадаам! Spark-ро дақиқ гуфтан хеле душвор буд, ки маълумот чӣ гуна тақсим карда шудааст. Ва ҳатто вақте ки ман ин корро кардам, маълум шуд, ки қисмҳо аз ҳад зиёд буданд (95 ҳазор), ва вақте ки ман истифода кардам coalesce шумораи онҳоро ба ҳудуди оқилона кам карданд, ин тақсимоти маро вайрон кард. Ман боварӣ дорам, ки инро метавон ислоҳ кард, аммо пас аз чанд рӯзи ҷустуҷӯ ман роҳи ҳалли худро наёфтам. Дар ниҳоят ман ҳама вазифаҳоро дар Spark анҷом додам, гарчанде ки ин муддатро гирифт ва файлҳои тақсимшудаи Паркетҳои ман чандон хурд набуданд (~200 КБ). Бо вуҷуди ин, маълумот дар он ҷое буд, ки лозим буд.

Таҳлили 25TB бо истифода аз AWK ва R
Хеле хурд ва нобаробар, аҷиб!

Санҷиши дархостҳои маҳаллии Spark

Ман чӣ омӯхтам: Spark ҳангоми ҳалли масъалаҳои оддӣ хароҷоти зиёд дорад.

Бо зеркашии маълумот дар формати оқилона, ман тавонистам суръатро санҷам. Скрипти R-ро барои кор кардани сервери Spark-и маҳаллӣ насб кунед ва сипас чаҳорчӯбаи маълумоти Sparkро аз нигаҳдории гурӯҳи муайяншудаи Паркет (бин) бор кунед. Ман кӯшиш кардам, ки ҳама маълумотро бор кунам, аммо натавонистам Sparklyr-ро бифаҳмам, ки тақсимотро эътироф кунад.

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)

Иҷрои он 29,415 сонияро дар бар гирифт. Хеле беҳтар, аммо барои санҷиши оммавии чизе на он қадар хуб. Илова бар ин, ман наметавонистам корҳоро бо кэш суръат бахшам, зеро вақте ки ман кӯшиш кардам, ки чаҳорчӯбаи додаҳоро дар хотира кэш кунам, Spark ҳамеша суқут мекард, ҳатто вақте ки ман зиёда аз 50 ГБ хотираро ба маҷмӯи додаҳо, ки вазни камтар аз 15 вазн дошт, ҷудо карда будам.

Бозгашт ба AWK

Ман чӣ омӯхтам: Массивҳои ассотсиативӣ дар AWK хеле самаранок мебошанд.

Ман фаҳмидам, ки ман метавонам ба суръати баландтар ноил шавам. Ман инро дар як аҷиб ба ёд овардам Дарси AWK аз ҷониби Брюс Барнетт Ман дар бораи хусусияти аҷибе бо номи " хондаммассивҳои ассотсиативӣ" Аслан, ин ҷуфтҳои калидӣ-арзиш мебошанд, ки бо баъзе сабабҳо дар AWK ба таври дигар номида мешуданд ва аз ин рӯ, ман дар бораи онҳо чандон фикр намекардам. Роман Чепляка ёдовар шуд, ки истилоҳи «массивҳои ассотсиативӣ» аз истилоҳи «ҷуфти калид-арзиш» хеле қадимтар аст. Ҳатто агар шумо Калид-арзишро дар Google Ngram ҷустуҷӯ кунед, шумо ин истилоҳро дар он ҷо нахоҳед дид, аммо шумо массивҳои ассотсиативиро хоҳед ёфт! Илова бар ин, "ҷуфти калид-арзиш" аксар вақт бо пойгоҳи додаҳо алоқаманд аст, аз ин рӯ муқоиса кардани он бо hasshmap хеле маъно дорад. Ман фаҳмидам, ки ман метавонам ин массивҳои ассотсиативиро барои пайваст кардани SNP-ҳои худ бо ҷадвали бин ва маълумоти хом бидуни истифодаи Spark истифода барам.

Барои ин, дар скрипти AWK ман блокро истифода кардам BEGIN. Ин як порчаи кодест, ки пеш аз интиқоли сатри якуми маълумот ба қисми асосии скрипт иҷро карда мешавад.

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"
}

гурӯҳ while(getline...) ҳамаи сатрҳоро аз гурӯҳи CSV (бин) бор кард, сутуни якумро (номи SNP) ҳамчун калиди массиви ассотсиативӣ таъин кунед bin ва арзиши дуюм (гурӯҳ) ҳамчун арзиш. Баъд дар блок { }, ки дар ҳама сатрҳои файли асосӣ иҷро мешавад, ҳар як сатр ба файли баромад фиристода мешавад, ки вобаста ба гурӯҳи худ (бин) номи беназир мегирад: ..._bin_"bin[$1]"_....

Тағйирёбандаҳо batch_num и chunk_id ба маълумоти аз ҷониби лӯла додашуда мувофиқат карда, аз ҳолати мусобиқа канорагирӣ кард ва ҳар як риштаи иҷрошаванда иҷро шуд parallel, ба файли беназири худ навишт.

Азбаски ман тамоми маълумоти хомро ба ҷузвдонҳо дар хромосомаҳои боқимондаи таҷрибаи қаблии худ бо AWK пароканда кардам, акнун ман метавонам скрипти дигари Bash нависам, то як хромосомаро дар як вақт коркард кунад ва маълумоти амиқтар тақсимшударо ба 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/*

Скрипт аз ду бахш иборат аст parallel.

Дар бахши аввал маълумот аз ҳама файлҳои дорои маълумот дар бораи хромосомаи дилхоҳ хонда мешавад, пас ин маълумот дар байни риштаҳо тақсим карда мешавад, ки файлҳоро ба гурӯҳҳои мувофиқ (бин) тақсим мекунанд. Барои пешгирӣ кардани шароити мусобиқа ҳангоми навиштани риштаҳои сершумор ба як файл, AWK номҳои файлро барои навиштани маълумот ба ҷойҳои гуногун интиқол медиҳад, масалан. chr_10_bin_52_batch_2_aa.csv. Дар натиҷа, дар диск бисёр файлҳои хурд сохта мешаванд (барои ин ман ҳаҷми терабайтии EBS-ро истифода кардам).

Конвейер аз участкам дуюм parallel тавассути гурӯҳҳо (бин) мегузарад ва файлҳои инфиродии онҳоро ба CSV умумӣ муттаҳид мекунад в catва баъд барои содирот мефиристад.

Пахш дар Р?

Ман чӣ омӯхтам: Шумо метавонед тамос гиред stdin и stdout аз скрипти R, ва аз ин рӯ онро дар лӯла истифода баред.

Шумо шояд ин сатрро дар скрипти Bash-и худ мушоҳида кардаед: ...cat chunked/*_bin_{}_*.csv | ./upload_as_rds.R.... Он ҳамаи файлҳои гурӯҳбандиро (бин) ба скрипти R дар зер тарҷума мекунад. {} техникаи махсус аст parallel, ки ҳама гуна маълумотеро, ки ба ҷараёни муқарраршуда мефиристад, мустақиман ба худи фармон дохил мекунад. Варианти {#} ID риштаи беназирро таъмин мекунад ва {%} рақами ҷойи корро намояндагӣ (такрор, вале ҳеҷ гоҳ ҳамзамон). Рӯйхати ҳамаи вариантҳоро дар он пайдо кардан мумкин аст ҳуҷҷатгузорӣ.

#!/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
)

Вақте ки тағирёбанда file("stdin") интиқол дода мешавад readr::read_csv, маълумоте, ки ба скрипти R тарҷума шудааст, ба чаҳорчӯба бор карда мешавад, ки он гоҳ дар шакл аст .rds- бо истифода аз файл aws.s3 бевосита ба S3 навишта шудааст.

RDS чизе монанди як версияи навраси Паркет аст, ки бидуни нигоҳдории баландгӯякҳо.

Пас аз хатми скрипти Bash ман як баста гирифтам .rds-файлҳое, ки дар S3 ҷойгиранд, ба ман имкон доданд, ки фишурдасозии самаранок ва намудҳои дарунсохтро истифода барам.

Сарфи назар аз истифодаи тормоз R, ҳама чиз хеле зуд кор кард. Тааҷҷубовар нест, ки қисмҳои R, ки маълумотро мехонанд ва менависанд, хеле оптимизатсия шудаанд. Пас аз санҷиш дар як хромосомаи миёнаҳаҷм, кор дар як мисоли C5n.4xl тақрибан ду соат анҷом ёфт.

Маҳдудиятҳои S3

Ман чӣ омӯхтам: Бо шарофати татбиқи роҳи оқилона, S3 метавонад файлҳои зиёдеро идора кунад.

Ман хавотир будам, ки оё S3 метавонад файлҳои зиёди ба он интиқолшударо идора кунад. Ман метавонистам номҳои файлро фаҳмонам, аммо S3 онҳоро чӣ гуна ҷустуҷӯ мекунад?

Таҳлили 25TB бо истифода аз AWK ва R
Ҷузвдонҳо дар S3 танҳо барои намоиш ҳастанд, дар асл система ба рамз манфиатдор нест /. Аз саҳифаи FAQ S3.

Чунин ба назар мерасад, ки S3 роҳи як файли мушаххасро ҳамчун калиди оддӣ дар як навъ ҷадвали ҳаш ё пойгоҳи додаҳои ҳуҷҷатӣ нишон медиҳад. Сатилро метавон ҳамчун ҷадвал баррасӣ кард ва файлҳоро сабти ин ҷадвал ҳисоб кардан мумкин аст.

Азбаски суръат ва самаранокӣ барои ба даст овардани фоида дар Амазонка муҳим аст, тааҷҷубовар нест, ки ин системаи калидӣ ҳамчун файл ба таври бениҳоят оптимизатсия карда шудааст. Ман кӯшиш кардам, ки мувозинатро пайдо кунам: то ки ман дархостҳои зиёде надошта бошам, аммо дархостҳо зуд иҷро шаванд. Маълум шуд, ки беҳтараш тақрибан 20 ҳазор файли биниро созед. Ман фикр мекунам, ки агар мо оптимизатсияро идома диҳем, мо метавонем суръати афзоишро ба даст орем (масалан, танҳо барои маълумот як сатили махсус созем ва ба ин васила андозаи ҷадвали ҷустуҷӯро кам кунем). Аммо барои озмоишҳои минбаъда вақт ва пул набуд.

Дар бораи мутобиқати кросс чӣ гуфтан мумкин аст?

Он чизе, ки ман омӯхтам: Сабаби рақами яки вақти беҳуда беҳтар кардани усули нигаҳдории шумост.

Дар ин лаҳза, хеле муҳим аст, ки аз худ бипурсед: "Чаро формати хусусии файлро истифода баред?" Сабаб дар суръати боркунӣ (файлҳои gzip CSV барои бор кардан 7 маротиба зиёдтар вақт лозим буд) ва мутобиқат бо ҷараёнҳои кории мост. Ман метавонам аз нав дида бароям, ки оё R метавонад файлҳои Паркетро (ё тир) бе сарбории Spark ба осонӣ бор кунад. Ҳама дар лабораторияи мо R-ро истифода мебаранд ва агар ба ман лозим ояд, ки маълумотро ба формати дигар табдил диҳам, ман то ҳол маълумоти аслии матнро дорам, бинобар ин ман метавонам лӯларо дубора иҷро кунам.

Тақсимоти кор

Ман чӣ омӯхтам: Кӯшиш накунед, ки корҳоро дастӣ оптимизатсия кунед, бигзор компютер ин корро кунад.

Ман ҷараёни корро дар як хромосома ислоҳ кардам, ҳоло ман бояд ҳамаи маълумоти дигарро коркард кунам.
Ман мехостам, ки якчанд мисолҳои EC2-ро барои табдилдиҳӣ эҷод кунам, аммо дар айни замон ман аз гирифтани сарбории хеле нобаробар дар корҳои гуногуни коркард метарсидам (чунон ки Spark аз қисмҳои нобаробар азоб мекашид). Илова бар ин, ман ба баланд бардоштани як мисол барои як хромосома манфиатдор набудам, зеро барои ҳисобҳои AWS маҳдудияти пешфарз аз 10 мисол вуҷуд дорад.

Пас аз он ман қарор додам, ки дар R скрипт нависам, то ҷойҳои коркардро оптимизатсия кунам.

Аввалан, ман аз S3 пурсидам, ки ҳар як хромосома чӣ қадар фазои нигоҳдорӣ ишғол мекунад.

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

Сипас ман функсияеро навиштам, ки андозаи умумиро мегирад, тартиби хромосомаҳоро омехта мекунад ва онҳоро ба гурӯҳҳо тақсим мекунад. num_jobs ва ба шумо мегӯяд, ки андозаи тамоми корҳои коркард то чӣ андоза гуногунанд.

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]>

Сипас ман бо истифода аз purrr ҳазорҳо омехта давидаму беҳтаринашро интихоб кардам.

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

Ҳамин тавр, ман як қатор вазифаҳоро анҷом додам, ки андозаашон хеле монанд буданд. Он гоҳ танҳо он чизе буд, ки скрипти қаблии Bash-ро дар як ҳалқаи калон печонед for. Барои навиштани ин оптимизатсия тақрибан 10 дақиқа вақт лозим буд. Ва ин хеле камтар аз он аст, ки ман барои эҷоди дастӣ вазифаҳо сарф мекардам, агар онҳо мувозинат надошта бошанд. Аз ин рӯ, ман фикр мекунам, ки ман бо ин оптимизатсияи пешакӣ дуруст будам.

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

Дар охир ман фармони хомӯширо илова мекунам:

sudo shutdown -h now

... ва ҳама чиз кор кард! Бо истифода аз AWS CLI, ман бо истифода аз опсия мисолҳоро бардоштам user_data ба онҳо скриптҳои Bash супоришҳои худро барои коркард дод. Онҳо ба таври худкор кор карданд ва хомӯш шуданд, бинобар ин ман барои қувваи коркарди иловагӣ пардохт накардам.

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

Биёед борбандӣ кунем!

Ман чӣ омӯхтам: API бояд ба хотири осонӣ ва чандирии истифода содда бошад.

Дар ниҳоят ман маълумотро дар ҷой ва шакли дуруст гирифтам. Танҳо он чизе, ки боқӣ мондааст, содда кардани раванди истифодаи маълумот буд, то барои ҳамкасбони ман осонтар шавад. Ман мехостам як API оддӣ барои эҷоди дархостҳо созам. Агар дар оянда ман қарор диҳам, ки аз .rds ба файлҳои Паркет, пас ин бояд барои ман мушкилот бошад, на барои ҳамкорони ман. Барои ин ман тасмим гирифтам, ки бастаи дохилии R созам.

Сохта ва ҳуҷҷатгузорӣ бастаи хеле соддаро дар бар мегирад, ки танҳо чанд функсияҳои дастрасии маълумотро дар атрофи як функсия ташкил карда шудаанд get_snp. Ман инчунин барои ҳамкорони худ як вебсайт сохтам pkgdown, то онҳо метавонанд ба осонӣ мисолҳо ва ҳуҷҷатҳоро бубинанд.

Таҳлили 25TB бо истифода аз AWK ва R

Кэшкунии интеллектуалӣ

Ман чӣ омӯхтам: Агар маълумоти шумо хуб омода карда шуда бошад, кэшкунӣ осон хоҳад буд!

Азбаски яке аз ҷараёнҳои асосии корӣ ҳамон модели таҳлилро ба бастаи SNP татбиқ мекард, ман қарор додам, ки биннингро ба манфиати худ истифода барам. Ҳангоми интиқоли маълумот тавассути SNP, ҳама маълумот аз гурӯҳ (бин) ба объекти баргардонида замима карда мешавад. Яъне, дархостҳои кӯҳна метавонанд (дар назария) коркарди дархостҳои навро суръат бахшанд.

# 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
  }
...

Ҳангоми сохтани баста, ман бисёр меъёрҳоро иҷро кардам, то суръатро ҳангоми истифодаи усулҳои гуногун муқоиса кунам. Ман тавсия медиҳам, ки инро фаромӯш накунам, зеро баъзан натиҷаҳо ғайричашмдошт мешаванд. Барои намуна, dplyr::filter нисбат ба гирифтани сатрҳо бо истифода аз филтри асоси индексатсия хеле тезтар буд ва дарёфти як сутун аз чаҳорчӯбаи маълумотҳои филтршуда назар ба истифодаи синтаксиси индексатсия хеле тезтар буд.

Лутфан қайд кунед, ки объект prev_snp_results калидро дар бар мегирад snps_in_bin. Ин массиви ҳамаи SNP-ҳои беназир дар гурӯҳ (бин) мебошад, ки ба шумо имкон медиҳад, ки зуд тафтиш кунед, ки оё шумо аллакай аз дархости қаблӣ маълумот доред. Он инчунин тавассути ин код гузаришро тавассути ҳама SNP-ҳои гурӯҳ (бин) осон мекунад:

# 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 
}

натиҷаҳои

Ҳоло мо метавонем моделҳо ва сенарияҳоеро, ки қаблан барои мо дастнорас буданд, иҷро кунем (ва ба таври ҷиддӣ оғоз кардем). Беҳтарин чиз он аст, ки ҳамкорони лаборатории ман набояд дар бораи мушкилот фикр кунанд. Онҳо танҳо як функсия доранд, ки кор мекунад.

Ва гарчанде ки баста ба онҳо тафсилотро нигоҳ медорад, ман кӯшиш кардам, ки формати маълумотро ба қадри кофӣ содда созам, ки онҳо фаҳманд, ки агар ман пагоҳ ногаҳон нопадид шавам...

Суръат ба таври намоён афзуд. Мо одатан порчаҳои геномҳои аз ҷиҳати функсионалӣ муҳимро скан мекунем. Пештар, мо ин корро карда наметавонистем (ин хеле гарон шуд), аммо ҳоло, ба шарофати сохтори гурӯҳӣ (бин) ва кэш, дархост барои як SNP ба ҳисоби миёна камтар аз 0,1 сонияро мегирад ва истифодаи додаҳо то ҳадде аст. паст аст, ки хароҷот барои S3 чормағз аст.

хулоса

Ин мақола умуман дастур нест. Ҳалли инфиродӣ шуд ва қариб албатта оптималӣ нест. Баръакс, ин сафарнома аст. Ман мехоҳам, ки дигарон фаҳманд, ки ин гуна қарорҳо дар сар ба таври комил ташаккул наёфтаанд, онҳо натиҷаи озмоиш ва хатогиҳо мебошанд. Инчунин, агар шумо дар ҷустуҷӯи олими маълумот бошед, дар хотир доред, ки истифодаи самараноки ин асбобҳо таҷриба талаб мекунад ва таҷриба пулро талаб мекунад. Ман хушҳолам, ки имкони пардохт кардан доштам, аммо бисёре аз дигарон, ки ҳамон корро аз ман беҳтар иҷро карда метавонанд, ҳеҷ гоҳ аз сабаби набудани пул имкони ҳатто кӯшиш карданро надоранд.

Воситаҳои бузурги додаҳо бисёрҷониба мебошанд. Агар шумо вақт дошта бошед, шумо метавонед бо истифода аз усулҳои тозакунӣ, нигоҳдорӣ ва истихроҷи маълумоти оқилона ҳалли тезтар нависед. Дар ниҳоят, он ба таҳлили хароҷот ва фоида меояд.

Он чизе ки ман омӯхтам:

  • роҳи арзони таҳлили 25 TB дар як вақт вуҷуд надорад;
  • аз андозаи файлҳои Паркет ва ташкили онҳо эҳтиёт шавед;
  • Қисмҳо дар Spark бояд мутавозин бошанд;
  • Умуман, ҳеҷ гоҳ кӯшиш накунед, ки 2,5 миллион қисмҳо созед;
  • Мураттабсозӣ то ҳол мушкил аст, ба мисли таъсиси Spark;
  • баъзан маълумоти махсус ҳалли махсусро талаб мекунад;
  • Ҷамъоварии шарора зуд аст, аммо тақсимкунӣ ҳоло ҳам гарон аст;
  • вақте ки онҳо ба шумо асосҳоро таълим медиҳанд, хоб накунед, шояд касе дар солҳои 1980 мушкили шуморо ҳал карда бошад;
  • gnu parallel - ин чизи ҷодугарӣ аст, ҳама бояд аз он истифода баранд;
  • Spark маълумоти фишурданашударо дӯст медорад ва якҷоя кардани қисмҳоро дӯст намедорад;
  • Spark ҳангоми ҳалли масъалаҳои оддӣ хароҷоти зиёд дорад;
  • Массивҳои ассотсиативии AWK хеле самаранок мебошанд;
  • тамос гирифта метавонед stdin и stdout аз скрипти R, ва аз ин рӯ онро дар қубур истифода баред;
  • Бо шарофати татбиқи роҳи оқилона, S3 метавонад файлҳои зиёдеро коркард кунад;
  • Сабаби асосии бехуда сарф кардани вақт пеш аз мӯҳлат оптимизатсия кардани усули нигоҳдории шумо мебошад;
  • кӯшиш накунед, ки вазифаҳоро дастӣ оптимизатсия кунед, бигзор онро компютер иҷро кунад;
  • API бояд ба хотири осонӣ ва чандирии истифода содда бошад;
  • Агар маълумоти шумо хуб омода карда шуда бошад, кэшкунӣ осон хоҳад буд!

Манбаъ: will.com

Илова Эзоҳ