AWK మరియు R ఉపయోగించి 25TBని అన్వయించడం

AWK మరియు R ఉపయోగించి 25TBని అన్వయించడం
ఈ కథనాన్ని ఎలా చదవాలి: వచనం చాలా పొడవుగా మరియు అస్తవ్యస్తంగా ఉన్నందుకు నేను క్షమాపణలు కోరుతున్నాను. మీ సమయాన్ని ఆదా చేయడానికి, నేను ప్రతి అధ్యాయాన్ని "నేను నేర్చుకున్నది" పరిచయంతో ప్రారంభిస్తాను, ఇది ఒకటి లేదా రెండు వాక్యాలలో అధ్యాయం యొక్క సారాంశాన్ని సంగ్రహిస్తుంది.

"నాకు పరిష్కారం చూపండి!" నేను ఎక్కడి నుండి వచ్చాను అని మీరు చూడాలనుకుంటే, "మరింత ఇన్వెంటివ్ అవ్వడం" అనే అధ్యాయానికి వెళ్లండి, కానీ వైఫల్యం గురించి చదవడం మరింత ఆసక్తికరంగా మరియు ఉపయోగకరంగా ఉంటుందని నేను భావిస్తున్నాను.

పెద్ద మొత్తంలో ముడి DNA సీక్వెన్స్‌లను (సాంకేతికంగా SNP చిప్) ప్రాసెస్ చేయడానికి ఒక ప్రక్రియను సెటప్ చేయడం నాకు ఇటీవలే అప్పగించబడింది. తదుపరి మోడలింగ్ మరియు ఇతర పనుల కోసం ఇచ్చిన జన్యు స్థానం (SNP అని పిలుస్తారు) గురించి డేటాను త్వరగా పొందడం అవసరం. R మరియు AWKని ఉపయోగించి, నేను డేటాను సహజమైన రీతిలో శుభ్రపరచగలిగాను మరియు నిర్వహించగలిగాను, ప్రశ్న ప్రాసెసింగ్‌ను బాగా వేగవంతం చేసాను. ఇది నాకు అంత సులభం కాదు మరియు అనేక పునరావృత్తులు అవసరం. ఈ కథనం నా తప్పులలో కొన్నింటిని నివారించడంలో మీకు సహాయం చేస్తుంది మరియు నేను ఏమి ముగించాను.

మొదట, కొన్ని పరిచయ వివరణలు.

డేటా

మా విశ్వవిద్యాలయ జన్యు సమాచార ప్రాసెసింగ్ కేంద్రం మాకు 25 TB TSV రూపంలో డేటాను అందించింది. నేను వాటిని 5 ప్యాకేజీలుగా విభజించాను, Gzip ద్వారా కంప్రెస్ చేయబడింది, వీటిలో ప్రతి ఒక్కటి 240 నాలుగు-గిగాబైట్ ఫైల్‌లను కలిగి ఉన్నాయి. ప్రతి అడ్డు వరుస ఒక వ్యక్తి నుండి ఒక SNP కోసం డేటాను కలిగి ఉంది. మొత్తంగా, ~ 2,5 మిలియన్ SNP లు మరియు ~ 60 వేల మంది వ్యక్తులపై డేటా ప్రసారం చేయబడింది. SNP సమాచారంతో పాటు, ఫైల్‌లు రీడ్ ఇంటెన్సిటీ, విభిన్న యుగ్మ వికల్పాల ఫ్రీక్వెన్సీ మొదలైన వివిధ లక్షణాలను ప్రతిబింబించే సంఖ్యలతో అనేక నిలువు వరుసలను కలిగి ఉన్నాయి. విశిష్ట విలువలతో మొత్తం 30 నిలువు వరుసలు ఉన్నాయి.

లక్ష్యం

ఏదైనా డేటా మేనేజ్‌మెంట్ ప్రాజెక్ట్ మాదిరిగా, డేటా ఎలా ఉపయోగించబడుతుందో నిర్ణయించడం చాలా ముఖ్యమైన విషయం. ఈ విషయంలో మేము SNP ఆధారంగా SNP కోసం మోడల్‌లు మరియు వర్క్‌ఫ్లోలను ఎక్కువగా ఎంచుకుంటాము. అంటే, మనకు ఒకేసారి ఒక SNPలో మాత్రమే డేటా అవసరం. 2,5 మిలియన్ల SNPలలో ఒకదానితో అనుబంధించబడిన అన్ని రికార్డ్‌లను వీలైనంత సులభంగా, త్వరగా మరియు చౌకగా ఎలా తిరిగి పొందాలో నేను నేర్చుకోవలసి వచ్చింది.

దీన్ని ఎలా చేయకూడదు

తగిన క్లిచ్‌ని కోట్ చేయడానికి:

నేను వెయ్యి సార్లు విఫలం కాలేదు, ప్రశ్నకు అనుకూలమైన ఫార్మాట్‌లో కొంత డేటాను అన్వయించకుండా ఉండటానికి నేను వెయ్యి మార్గాలను కనుగొన్నాను.

మొదటి ప్రయత్నం

నేను ఏమి నేర్చుకున్నాను: ఒకేసారి 25 TBని అన్వయించడానికి చౌక మార్గం లేదు.

వాండర్‌బిల్ట్ యూనివర్శిటీలో “అడ్వాన్స్‌డ్ మెథడ్స్ ఫర్ బిగ్ డేటా ప్రాసెసింగ్” కోర్సు తీసుకున్న తర్వాత, ట్రిక్ బ్యాగ్‌లో ఉందని నేను ఖచ్చితంగా అనుకుంటున్నాను. మొత్తం డేటాను అమలు చేయడానికి మరియు ఫలితాన్ని నివేదించడానికి హైవ్ సర్వర్‌ని సెటప్ చేయడానికి బహుశా ఒకటి లేదా రెండు గంటలు పట్టవచ్చు. మా డేటా AWS S3లో నిల్వ చేయబడినందున, నేను సేవను ఉపయోగించాను ఎథీనా, ఇది S3 డేటాకు హైవ్ SQL ప్రశ్నలను వర్తింపజేయడానికి మిమ్మల్ని అనుమతిస్తుంది. మీరు హైవ్ క్లస్టర్‌ను సెటప్/రైజ్ చేయాల్సిన అవసరం లేదు మరియు మీరు వెతుకుతున్న డేటాకు మాత్రమే చెల్లించాలి.

నేను ఎథీనాకు నా డేటా మరియు దాని ఆకృతిని చూపించిన తర్వాత, నేను ఇలాంటి ప్రశ్నలతో కొన్ని పరీక్షలను నిర్వహించాను:

select * from intensityData limit 10;

మరియు త్వరగా నిర్మాణాత్మక ఫలితాలను పొందింది. సిద్ధంగా ఉంది.

మేము మా పనిలో డేటాను ఉపయోగించడానికి ప్రయత్నించే వరకు...

మోడల్‌ని పరీక్షించడానికి మొత్తం SNP సమాచారాన్ని తీసివేయమని నన్ను అడిగారు. నేను ప్రశ్నను అమలు చేసాను:


select * from intensityData 
where snp = 'rs123456';

... మరియు వేచి ప్రారంభించారు. ఎనిమిది నిమిషాలు మరియు 4 TB కంటే ఎక్కువ అభ్యర్థించిన డేటా తర్వాత, నేను ఫలితాన్ని అందుకున్నాను. కనుగొనబడిన డేటా పరిమాణం ఆధారంగా ఎథీనా ఛార్జీలు, టెరాబైట్‌కు $5. కాబట్టి ఈ ఒక్క అభ్యర్థన $20 మరియు ఎనిమిది నిమిషాల నిరీక్షణ ఖర్చు అవుతుంది. మొత్తం డేటాపై మోడల్‌ను అమలు చేయడానికి, మేము 38 సంవత్సరాలు వేచి ఉండి, $50 మిలియన్లు చెల్లించాల్సి వచ్చింది. సహజంగానే, ఇది మాకు తగినది కాదు.

పార్కెట్‌ని ఉపయోగించడం అవసరం ...

నేను ఏమి నేర్చుకున్నాను: మీ పార్కెట్ ఫైల్‌లు మరియు వాటి సంస్థ పరిమాణంతో జాగ్రత్తగా ఉండండి.

నేను మొదట అన్ని TSVలను మార్చడం ద్వారా పరిస్థితిని పరిష్కరించడానికి ప్రయత్నించాను పార్కెట్ ఫైల్స్. పెద్ద డేటా సెట్‌లతో పని చేయడానికి అవి సౌకర్యవంతంగా ఉంటాయి ఎందుకంటే వాటిలోని సమాచారం కాలమ్ రూపంలో నిల్వ చేయబడుతుంది: ప్రతి కాలమ్ దాని స్వంత మెమరీ/డిస్క్ విభాగంలో ఉంటుంది, టెక్స్ట్ ఫైల్‌లకు భిన్నంగా, అడ్డు వరుసలు ప్రతి నిలువు వరుసలోని అంశాలను కలిగి ఉంటాయి. మరియు మీరు ఏదైనా కనుగొనవలసి ఉంటే, అవసరమైన కాలమ్‌ను చదవండి. అదనంగా, ప్రతి ఫైల్ కాలమ్‌లో విలువల శ్రేణిని నిల్వ చేస్తుంది, కాబట్టి మీరు వెతుకుతున్న విలువ కాలమ్ పరిధిలో లేకుంటే, స్పార్క్ మొత్తం ఫైల్‌ను స్కాన్ చేసే సమయాన్ని వృథా చేయదు.

నేను ఒక సాధారణ పనిని అమలు చేసాను AWS జిగురు మా TSVలను పార్క్వెట్‌గా మార్చడానికి మరియు కొత్త ఫైల్‌లను ఎథీనాలోకి వదిలివేసింది. దాదాపు 5 గంటల సమయం పట్టింది. కానీ నేను అభ్యర్థనను అమలు చేసినప్పుడు, పూర్తి చేయడానికి అదే సమయం మరియు కొంచెం తక్కువ డబ్బు పట్టింది. వాస్తవం ఏమిటంటే, స్పార్క్, టాస్క్‌ను ఆప్టిమైజ్ చేయడానికి ప్రయత్నిస్తూ, ఒక TSV భాగాన్ని అన్‌ప్యాక్ చేసి, దాని స్వంత పారేకెట్ చంక్‌లో ఉంచింది. మరియు ప్రతి భాగం చాలా మంది వ్యక్తుల పూర్తి రికార్డులను కలిగి ఉండేంత పెద్దదిగా ఉన్నందున, ప్రతి ఫైల్ అన్ని SNPలను కలిగి ఉంటుంది, కాబట్టి స్పార్క్ దానికి అవసరమైన సమాచారాన్ని సేకరించేందుకు అన్ని ఫైల్‌లను తెరవవలసి ఉంటుంది.

ఆసక్తికరంగా, Parquet యొక్క డిఫాల్ట్ (మరియు సిఫార్సు చేయబడిన) కుదింపు రకం, స్నాపీ, విభజించబడదు. అందువల్ల, ప్రతి కార్యనిర్వాహకుడు పూర్తి 3,5 GB డేటాసెట్‌ను అన్‌ప్యాక్ చేసి డౌన్‌లోడ్ చేసే పనిలో చిక్కుకున్నారు.

AWK మరియు R ఉపయోగించి 25TBని అన్వయించడం

సమస్యను అర్థం చేసుకుందాం

నేను ఏమి నేర్చుకున్నాను: క్రమబద్ధీకరించడం కష్టం, ముఖ్యంగా డేటా పంపిణీ చేయబడితే.

సమస్య యొక్క సారాంశం ఇప్పుడు నాకు అర్థమైందని నాకు అనిపించింది. నేను డేటాను SNP కాలమ్ ద్వారా మాత్రమే క్రమబద్ధీకరించాలి, వ్యక్తుల ద్వారా కాదు. అప్పుడు అనేక SNP లు ప్రత్యేక డేటా భాగంలో నిల్వ చేయబడతాయి, ఆపై Parquet యొక్క "స్మార్ట్" ఫంక్షన్ "విలువ పరిధిలో ఉన్నట్లయితే మాత్రమే తెరవబడుతుంది" దాని అన్ని వైభవంగా చూపబడుతుంది. దురదృష్టవశాత్తు, క్లస్టర్‌లో చెల్లాచెదురుగా ఉన్న బిలియన్ల వరుసల ద్వారా క్రమబద్ధీకరించడం చాలా కష్టమైన పని.

"నేను పరధ్యానంలో ఉన్న విద్యార్థిని" అనే కారణంతో AWS ఖచ్చితంగా రీఫండ్‌ని జారీ చేయాలనుకోదు. నేను Amazon Glueలో సార్టింగ్ చేసిన తర్వాత, అది 2 రోజులు నడిచి క్రాష్ అయింది.

విభజన గురించి ఏమిటి?

నేను ఏమి నేర్చుకున్నాను: స్పార్క్‌లోని విభజనలు తప్పనిసరిగా సమతుల్యంగా ఉండాలి.

అప్పుడు నేను క్రోమోజోమ్‌లలో డేటాను విభజించాలనే ఆలోచనతో వచ్చాను. వాటిలో 23 ఉన్నాయి (మరియు మీరు మైటోకాన్డ్రియల్ DNA మరియు మ్యాప్ చేయని ప్రాంతాలను పరిగణనలోకి తీసుకుంటే మరికొన్ని).
ఇది డేటాను చిన్న భాగాలుగా విభజించడానికి మిమ్మల్ని అనుమతిస్తుంది. మీరు గ్లూ స్క్రిప్ట్‌లో స్పార్క్ ఎగుమతి ఫంక్షన్‌కు కేవలం ఒక లైన్‌ను జోడిస్తే partition_by = "chr", అప్పుడు డేటాను బకెట్లుగా విభజించాలి.

AWK మరియు R ఉపయోగించి 25TBని అన్వయించడం
జన్యువులో క్రోమోజోములు అని పిలువబడే అనేక శకలాలు ఉంటాయి.

దురదృష్టవశాత్తు, అది పని చేయలేదు. క్రోమోజోమ్‌లు వేర్వేరు పరిమాణాలను కలిగి ఉంటాయి, అంటే వివిధ మొత్తంలో సమాచారం. దీనర్థం ఏమిటంటే, స్పార్క్ కార్మికులకు పంపిన పనులు సమతుల్యంగా లేవు మరియు కొన్ని నోడ్‌లు ముందుగానే పూర్తయ్యాయి మరియు పనిలేకుండా ఉన్నాయి. అయినా పనులు పూర్తయ్యాయి. కానీ ఒక SNP కోసం అడుగుతున్నప్పుడు, అసమతుల్యత మళ్లీ సమస్యలను కలిగించింది. పెద్ద క్రోమోజోమ్‌లపై SNPలను ప్రాసెస్ చేసే ఖర్చు (అంటే, మనం డేటాను పొందాలనుకుంటున్న చోట) కేవలం 10 రెట్లు తగ్గింది. చాలా, కానీ సరిపోదు.

మనం దానిని ఇంకా చిన్న భాగాలుగా విభజిస్తే?

నేను ఏమి నేర్చుకున్నాను: 2,5 మిలియన్ల విభజనలను చేయడానికి ఎప్పుడూ ప్రయత్నించవద్దు.

నేను అన్నింటికి వెళ్లాలని నిర్ణయించుకున్నాను మరియు ప్రతి SNPని విభజించాను. విభజనలు సమాన పరిమాణంలో ఉన్నాయని ఇది నిర్ధారిస్తుంది. ఇది ఒక చెడ్డ ఆలోచన. నేను జిగురును ఉపయోగించాను మరియు అమాయక పంక్తిని జోడించాను partition_by = 'snp'. పని ప్రారంభించబడింది మరియు అమలు చేయడం ప్రారంభించింది. ఒక రోజు తర్వాత నేను తనిఖీ చేసాను మరియు S3కి ఇంకా ఏమీ వ్రాయలేదని చూశాను, కాబట్టి నేను పనిని చంపాను. Glue S3లో దాచిన స్థానానికి ఇంటర్మీడియట్ ఫైల్‌లను వ్రాస్తున్నట్లు కనిపిస్తోంది, చాలా ఫైల్‌లు, బహుశా కొన్ని మిలియన్లు. ఫలితంగా, నా తప్పు వెయ్యి డాలర్ల కంటే ఎక్కువ ఖర్చు అవుతుంది మరియు నా గురువును సంతోషపెట్టలేదు.

విభజన + క్రమబద్ధీకరణ

నేను ఏమి నేర్చుకున్నాను: స్పార్క్‌ని ట్యూన్ చేయడం వలె క్రమబద్ధీకరించడం ఇంకా కష్టం.

విభజనలో నా చివరి ప్రయత్నంలో నేను క్రోమోజోమ్‌లను విభజించి, ఆపై ప్రతి విభజనను క్రమబద్ధీకరించాను. సిద్ధాంతంలో, ఇది ప్రతి ప్రశ్నను వేగవంతం చేస్తుంది ఎందుకంటే కావలసిన 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లు క్రోమోజోమ్‌ల అంతటా సమానంగా పంపిణీ చేయబడవు, కాబట్టి సమూహ పరిమాణాలు చాలా మారుతూ ఉంటాయి.

AWK మరియు R ఉపయోగించి 25TBని అన్వయించడం

ఫలితంగా, నేను కేటగిరీలుగా (ర్యాంక్) స్థానాల విభజనకు వచ్చాను. ఇప్పటికే డౌన్‌లోడ్ చేయబడిన డేటాను ఉపయోగించి, నేను ప్రత్యేకమైన 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()

మొదట స్పార్క్‌తో ప్రయత్నించండి

నేను ఏమి నేర్చుకున్నాను: స్పార్క్ అగ్రిగేషన్ వేగంగా ఉంటుంది, కానీ విభజన ఇప్పటికీ ఖరీదైనది.

నేను ఈ చిన్న (2,5 మిలియన్ వరుసలు) డేటా ఫ్రేమ్‌ను స్పార్క్‌లో చదవాలనుకుంటున్నాను, దానిని ముడి డేటాతో కలిపి, ఆపై కొత్తగా జోడించిన కాలమ్ ద్వారా విభజించాలనుకుంటున్నాను 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(), కాబట్టి స్పార్క్ అన్ని నోడ్‌లకు డేటా ఫ్రేమ్‌ను పంపాలని తెలుసు. డేటా పరిమాణంలో చిన్నది మరియు అన్ని పనులకు అవసరమైనప్పుడు ఇది ఉపయోగకరంగా ఉంటుంది. లేకపోతే, స్పార్క్ స్మార్ట్‌గా ఉండటానికి ప్రయత్నిస్తుంది మరియు అవసరమైన విధంగా డేటాను పంపిణీ చేస్తుంది, ఇది మందగింపులకు కారణమవుతుంది.

మరలా, నా ఆలోచన పని చేయలేదు: పనులు కొంతకాలం పనిచేశాయి, యూనియన్‌ను పూర్తి చేశాయి, ఆపై విభజన ద్వారా ప్రారంభించబడిన కార్యనిర్వాహకుల వలె, వారు విఫలం కావడం ప్రారంభించారు.

AWKని జోడిస్తోంది

నేను ఏమి నేర్చుకున్నాను: మీకు బేసిక్స్ నేర్పుతున్నప్పుడు నిద్రపోకండి. ఖచ్చితంగా 1980లలో మీ సమస్యను ఎవరో ఇప్పటికే పరిష్కరించారు.

ఈ సమయం వరకు, స్పార్క్‌తో నా అన్ని వైఫల్యాలకు కారణం క్లస్టర్‌లోని డేటా గందరగోళం. బహుశా ముందస్తు చికిత్సతో పరిస్థితి మెరుగుపడవచ్చు. నేను ముడి టెక్స్ట్ డేటాను క్రోమోజోమ్‌ల నిలువు వరుసలుగా విభజించడానికి ప్రయత్నించాలని నిర్ణయించుకున్నాను, కాబట్టి స్పార్క్‌కి "ముందస్తు-విభజన" డేటాను అందించాలని నేను ఆశించాను.

కాలమ్ విలువల ద్వారా ఎలా విభజించాలో నేను StackOverflowలో శోధించాను మరియు కనుగొన్నాను అంత గొప్ప సమాధానం. AWKతో మీరు టెక్స్ట్ ఫైల్‌ను కాలమ్ విలువలతో విభజించవచ్చు, ఫలితాలను పంపడం కంటే స్క్రిప్ట్‌లో వ్రాయవచ్చు stdout.

దీన్ని ప్రయత్నించడానికి నేను బాష్ స్క్రిప్ట్‌ని వ్రాసాను. ప్యాక్ చేయబడిన 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 MB మెమరీని మాత్రమే ఉపయోగిస్తున్నానని తేలింది. సమస్యను పరిష్కరించడానికి మరియు చాలా డబ్బును కోల్పోకుండా ఉండటానికి, పనిని ఎలా సమాంతరంగా చేయాలో మేము గుర్తించాలి. అదృష్టవశాత్తూ, ఖచ్చితంగా అద్భుతమైన పుస్తకంలో కమాండ్ లైన్ వద్ద డేటా సైన్స్ నేను సమాంతరీకరణపై జెరాన్ జాన్సెన్స్ యొక్క అధ్యాయాన్ని కనుగొన్నాను. దాని నుండి నేను గురించి తెలుసుకున్నాను gnu parallel, Unixలో మల్టీథ్రెడింగ్‌ని అమలు చేయడానికి చాలా అనువైన పద్ధతి.

AWK మరియు R ఉపయోగించి 25TBని అన్వయించడం
నేను కొత్త ప్రక్రియను ఉపయోగించి విభజనను ప్రారంభించినప్పుడు, ప్రతిదీ బాగానే ఉంది, కానీ ఇప్పటికీ ఒక అడ్డంకి ఉంది - S3 వస్తువులను డిస్క్‌కి డౌన్‌లోడ్ చేయడం చాలా వేగంగా లేదు మరియు పూర్తిగా సమాంతరంగా లేదు. దీన్ని పరిష్కరించడానికి, నేను ఇలా చేసాను:

  1. S3 డౌన్‌లోడ్ దశను నేరుగా పైప్‌లైన్‌లో అమలు చేయడం సాధ్యమవుతుందని నేను కనుగొన్నాను, డిస్క్‌లో ఇంటర్మీడియట్ నిల్వను పూర్తిగా తొలగిస్తుంది. దీని అర్థం నేను డిస్క్‌కి ముడి డేటాను వ్రాయడాన్ని నివారించగలను మరియు AWSలో మరింత చిన్నదిగా మరియు అందువల్ల తక్కువ ధరలో నిల్వను ఉపయోగించగలను.
  2. జట్టు aws configure set default.s3.max_concurrent_requests 50 AWS CLI ఉపయోగించే థ్రెడ్‌ల సంఖ్యను బాగా పెంచింది (డిఫాల్ట్‌గా 10 ఉన్నాయి).
  3. నేను పేరులో n అక్షరంతో నెట్‌వర్క్ వేగం కోసం ఆప్టిమైజ్ చేసిన EC2 ఉదాహరణకి మారాను. n-ఇన్‌స్టాన్స్‌లను ఉపయోగిస్తున్నప్పుడు ప్రాసెసింగ్ పవర్ కోల్పోవడం లోడింగ్ వేగం పెరుగుదల ద్వారా భర్తీ చేయబడుతుందని నేను కనుగొన్నాను. చాలా పనుల కోసం నేను c5n.4xlని ఉపయోగించాను.
  4. మార్చబడింది gzippigz, ఇది ఒక 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' అని పేర్కొనాలి. అయ్యో.

కొత్తగా అన్వయించిన డేటాను ఉపయోగించడం

నేను ఏమి నేర్చుకున్నాను: స్పార్క్ కంప్రెస్డ్ డేటాను ఇష్టపడుతుంది మరియు విభజనలను కలపడం ఇష్టం లేదు.

ఇప్పుడు డేటా S3లో అన్‌ప్యాక్ చేయబడి (చదవండి: భాగస్వామ్యం చేయబడింది) మరియు సెమీ-ఆర్డర్ చేసిన ఆకృతిలో ఉంది మరియు నేను మళ్లీ స్పార్క్‌కి తిరిగి రాగలిగాను. నాకు ఆశ్చర్యం ఎదురుచూసింది: నేను కోరుకున్నది సాధించడంలో మళ్లీ విఫలమయ్యాను! డేటా ఎలా విభజించబడిందో స్పార్క్‌కు చెప్పడం చాలా కష్టం. మరియు నేను దీన్ని చేసినప్పుడు కూడా, చాలా ఎక్కువ విభజనలు (95 వేలు) ఉన్నాయని మరియు నేను ఉపయోగించినప్పుడు coalesce వారి సంఖ్యను సహేతుకమైన పరిమితులకు తగ్గించింది, ఇది నా విభజనను నాశనం చేసింది. ఇది పరిష్కరించబడుతుందని నేను ఖచ్చితంగా అనుకుంటున్నాను, కానీ రెండు రోజులు వెతికినా పరిష్కారం కనుగొనలేకపోయాను. నేను స్పార్క్‌లోని అన్ని పనులను పూర్తి చేసాను, అయితే దీనికి కొంత సమయం పట్టింది మరియు నా స్ప్లిట్ పార్కెట్ ఫైల్‌లు చాలా చిన్నవి కావు (~200 KB). అయితే, డేటా అవసరమైన చోట ఉంది.

AWK మరియు R ఉపయోగించి 25TBని అన్వయించడం
చాలా చిన్నది మరియు అసమానమైనది, అద్భుతమైనది!

స్థానిక స్పార్క్ ప్రశ్నలను పరీక్షిస్తోంది

నేను ఏమి నేర్చుకున్నాను: సాధారణ సమస్యలను పరిష్కరించేటప్పుడు స్పార్క్ చాలా ఓవర్ హెడ్ కలిగి ఉంటుంది.

డేటాను తెలివైన ఆకృతిలో డౌన్‌లోడ్ చేయడం ద్వారా, నేను వేగాన్ని పరీక్షించగలిగాను. స్థానిక Spark సర్వర్‌ని అమలు చేయడానికి R స్క్రిప్ట్‌ను సెటప్ చేయండి, ఆపై పేర్కొన్న Parquet సమూహం నిల్వ (బిన్) నుండి 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 సెకన్లు పట్టింది. చాలా ఉత్తమం, కానీ ఏదైనా సామూహిక పరీక్ష కోసం చాలా మంచిది కాదు. అదనంగా, నేను మెమరీలో డేటా ఫ్రేమ్‌ను కాష్ చేయడానికి ప్రయత్నించినప్పుడు, నేను 50 కంటే తక్కువ బరువున్న డేటాసెట్‌కి 15 GB కంటే ఎక్కువ మెమరీని కేటాయించినప్పటికీ, స్పార్క్ ఎల్లప్పుడూ క్రాష్ అవుతుంది కాబట్టి నేను కాషింగ్‌తో వేగవంతం చేయలేకపోయాను.

AWKకి తిరిగి వెళ్ళు

నేను ఏమి నేర్చుకున్నాను: AWKలోని అనుబంధ శ్రేణులు చాలా సమర్థవంతంగా పనిచేస్తాయి.

నేను అధిక వేగాన్ని సాధించగలనని గ్రహించాను. నేను దానిని అద్భుతంగా గుర్తుంచుకున్నాను బ్రూస్ బార్నెట్ ద్వారా AWK ట్యుటోరియల్ నేను "" అనే మంచి ఫీచర్ గురించి చదివాను.అనుబంధ శ్రేణులు" ముఖ్యంగా, ఇవి కీ-విలువ జతలు, కొన్ని కారణాల వల్ల AWKలో విభిన్నంగా పిలువబడతాయి మరియు అందువల్ల నేను వాటి గురించి పెద్దగా ఆలోచించలేదు. రోమన్ చెప్లియాకా "అసోసియేటివ్ అర్రేస్" అనే పదం "కీ-వాల్యూ పెయిర్" అనే పదం కంటే చాలా పాతదని గుర్తుచేసుకున్నారు. మీరు కూడా Google Ngramలో కీ-విలువను చూడండి, మీరు అక్కడ ఈ పదాన్ని చూడలేరు, కానీ మీరు అనుబంధ శ్రేణులను కనుగొంటారు! అదనంగా, “కీ-విలువ జత” చాలా తరచుగా డేటాబేస్‌లతో అనుబంధించబడుతుంది, కాబట్టి దీన్ని హ్యాష్‌మ్యాప్‌తో పోల్చడం చాలా సమంజసమైనది. స్పార్క్‌ని ఉపయోగించకుండానే నా SNPలను బిన్ టేబుల్ మరియు ముడి డేటాతో అనుబంధించడానికి ఈ అనుబంధ శ్రేణులను ఉపయోగించవచ్చని నేను గ్రహించాను.

దీన్ని చేయడానికి, 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తో నా మునుపటి ప్రయోగంలో మిగిలిపోయిన క్రోమోజోమ్‌లపై అన్ని ముడి డేటాను ఫోల్డర్‌లలోకి వెదజల్లినందున, ఇప్పుడు నేను ఒక సమయంలో ఒక క్రోమోజోమ్‌ను ప్రాసెస్ చేయడానికి మరియు 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ఆపై వాటిని ఎగుమతి కోసం పంపుతుంది.

R లో ప్రసారం చేస్తున్నారా?

నేను ఏమి నేర్చుకున్నాను: మీరు సంప్రదించవచ్చు stdin и stdout R స్క్రిప్ట్ నుండి, అందువల్ల పైప్‌లైన్‌లో దాన్ని ఉపయోగించండి.

మీరు మీ బాష్ స్క్రిప్ట్‌లో ఈ లైన్‌ని గమనించి ఉండవచ్చు: ...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 అనేది స్పీకర్ స్టోరేజ్‌లో ఎలాంటి అవాంతరాలు లేకుండా, పార్క్వెట్ యొక్క జూనియర్ వెర్షన్ లాంటిది.

బాష్ స్క్రిప్ట్ పూర్తి చేసిన తర్వాత నాకు ఒక బండిల్ వచ్చింది .rds-ఫైల్‌లు S3లో ఉన్నాయి, ఇది సమర్థవంతమైన కంప్రెషన్ మరియు అంతర్నిర్మిత రకాలను ఉపయోగించడానికి నన్ను అనుమతించింది.

బ్రేక్ R యొక్క ఉపయోగం ఉన్నప్పటికీ, ప్రతిదీ చాలా త్వరగా పనిచేసింది. డేటాను చదవడం మరియు వ్రాయడం వంటి R యొక్క భాగాలు అత్యంత ఆప్టిమైజ్ చేయబడటంలో ఆశ్చర్యం లేదు. ఒక మధ్యస్థ-పరిమాణ క్రోమోజోమ్‌పై పరీక్షించిన తర్వాత, దాదాపు రెండు గంటల్లో C5n.4xl సందర్భంలో జాబ్ పూర్తయింది.

S3 పరిమితులు

నేను ఏమి నేర్చుకున్నాను: స్మార్ట్ పాత్ అమలుకు ధన్యవాదాలు, S3 అనేక ఫైల్‌లను నిర్వహించగలదు.

S3 దానికి బదిలీ చేయబడిన అనేక ఫైల్‌లను నిర్వహించగలదా అని నేను ఆందోళన చెందాను. నేను ఫైల్ పేర్లను అర్ధవంతం చేయగలను, కానీ వాటి కోసం S3 ఎలా కనిపిస్తుంది?

AWK మరియు R ఉపయోగించి 25TBని అన్వయించడం
S3లోని ఫోల్డర్‌లు కేవలం ప్రదర్శన కోసం మాత్రమే, వాస్తవానికి సిస్టమ్ చిహ్నంపై ఆసక్తి చూపదు /. S3 FAQ పేజీ నుండి.

S3 ఒక నిర్దిష్ట ఫైల్‌కి పాత్‌ను ఒక విధమైన హాష్ టేబుల్ లేదా డాక్యుమెంట్-ఆధారిత డేటాబేస్‌లో సాధారణ కీగా సూచిస్తున్నట్లు కనిపిస్తోంది. బకెట్‌ను టేబుల్‌గా భావించవచ్చు మరియు ఫైల్‌లను ఆ పట్టికలోని రికార్డులుగా పరిగణించవచ్చు.

అమెజాన్‌లో లాభం పొందడానికి వేగం మరియు సామర్థ్యం ముఖ్యమైనవి కాబట్టి, ఈ కీ-యాజ్-ఫైల్-పాత్ సిస్టమ్ ఫ్రీకింగ్ ఆప్టిమైజ్ కావడంలో ఆశ్చర్యం లేదు. నేను బ్యాలెన్స్‌ని కనుగొనడానికి ప్రయత్నించాను: తద్వారా నేను చాలా గెట్ రిక్వెస్ట్‌లు చేయాల్సిన అవసరం లేదు, కానీ అభ్యర్థనలు త్వరగా అమలు చేయబడ్డాయి. సుమారు 20 వేల బిన్ ఫైళ్లను తయారు చేయడం ఉత్తమమని తేలింది. మేము ఆప్టిమైజ్ చేయడాన్ని కొనసాగిస్తే, మేము వేగం పెరుగుదలను సాధించగలమని నేను భావిస్తున్నాను (ఉదాహరణకు, డేటా కోసం ప్రత్యేక బకెట్‌ను తయారు చేయడం, తద్వారా శోధన పట్టిక పరిమాణాన్ని తగ్గించడం). కానీ తదుపరి ప్రయోగాలకు సమయం లేదా డబ్బు లేదు.

క్రాస్ అనుకూలత గురించి ఏమిటి?

నేను నేర్చుకున్నది: సమయం వృధా కావడానికి మొదటి కారణం మీ నిల్వ పద్ధతిని ముందుగానే ఆప్టిమైజ్ చేయడం.

ఈ సమయంలో, మిమ్మల్ని మీరు ఇలా ప్రశ్నించుకోవడం చాలా ముఖ్యం: “యాజమాన్య ఫైల్ ఫార్మాట్‌ను ఎందుకు ఉపయోగించాలి?” కారణం లోడింగ్ వేగం (gzipped CSV ఫైల్‌లు లోడ్ కావడానికి 7 రెట్లు ఎక్కువ సమయం పట్టింది) మరియు మా వర్క్‌ఫ్లోలకు అనుకూలత. R స్పార్క్ లోడ్ లేకుండా పార్క్వెట్ (లేదా బాణం) ఫైల్‌లను సులభంగా లోడ్ చేయగలదా అని నేను పునఃపరిశీలించవచ్చు. మా ల్యాబ్‌లోని ప్రతి ఒక్కరూ Rని ఉపయోగిస్తున్నారు మరియు నేను డేటాను మరొక ఫార్మాట్‌కి మార్చాల్సిన అవసరం ఉన్నట్లయితే, నా వద్ద ఇప్పటికీ అసలైన టెక్స్ట్ డేటా ఉంది, కాబట్టి నేను పైప్‌లైన్‌ను మళ్లీ అమలు చేయగలను.

పని విభజన

నేను ఏమి నేర్చుకున్నాను: జాబ్‌లను మాన్యువల్‌గా ఆప్టిమైజ్ చేయడానికి ప్రయత్నించవద్దు, కంప్యూటర్‌ని చేయనివ్వండి.

నేను ఒక క్రోమోజోమ్‌లో వర్క్‌ఫ్లో డీబగ్ చేసాను, ఇప్పుడు నేను అన్ని ఇతర డేటాను ప్రాసెస్ చేయాలి.
నేను మార్పిడి కోసం అనేక EC2 ఉదంతాలను పెంచాలనుకున్నాను, కానీ అదే సమయంలో వివిధ ప్రాసెసింగ్ జాబ్‌లలో (స్పార్క్ అసమతుల్య విభజనలతో బాధపడ్డట్లే) చాలా అసమతుల్యమైన లోడ్‌ను పొందడం గురించి నేను భయపడ్డాను. అదనంగా, 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)

కాబట్టి నేను పరిమాణంలో చాలా పోలి ఉండే టాస్క్‌ల సెట్‌తో ముగించాను. అప్పుడు మిగిలింది నా మునుపటి బాష్ స్క్రిప్ట్‌ను పెద్ద లూప్‌లో చుట్టడం 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 ప్రాసెసింగ్ కోసం వారి టాస్క్‌ల బాష్ స్క్రిప్ట్‌లను వారికి ఇచ్చింది. అవి ఆటోమేటిక్‌గా పరిగెత్తాయి మరియు షట్ డౌన్ అయ్యాయి, కాబట్టి నేను అదనపు ప్రాసెసింగ్ పవర్ కోసం చెల్లించడం లేదు.

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, కాబట్టి వారు సులభంగా ఉదాహరణలు మరియు డాక్యుమెంటేషన్‌ను చూడగలరు.

AWK మరియు R ఉపయోగించి 25TBని అన్వయించడం

స్మార్ట్ కాషింగ్

నేను ఏమి నేర్చుకున్నాను: మీ డేటా బాగా సిద్ధమైనట్లయితే, కాషింగ్ సులభం అవుతుంది!

ప్రధాన వర్క్‌ఫ్లోలలో ఒకటి అదే విశ్లేషణ నమూనాను 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ని అన్వయించడానికి చౌక మార్గం లేదు;
  • మీ పార్కెట్ ఫైల్‌లు మరియు వాటి సంస్థ యొక్క పరిమాణంతో జాగ్రత్తగా ఉండండి;
  • స్పార్క్‌లోని విభజనలు సమతుల్యంగా ఉండాలి;
  • సాధారణంగా, 2,5 మిలియన్ల విభజనలను చేయడానికి ఎప్పుడూ ప్రయత్నించవద్దు;
  • స్పార్క్‌ని ఏర్పాటు చేయడం వంటి క్రమబద్ధీకరణ ఇప్పటికీ కష్టం;
  • కొన్నిసార్లు ప్రత్యేక డేటాకు ప్రత్యేక పరిష్కారాలు అవసరం;
  • స్పార్క్ అగ్రిగేషన్ వేగంగా ఉంటుంది, కానీ విభజన ఇప్పటికీ ఖరీదైనది;
  • వారు మీకు బేసిక్స్ నేర్పినప్పుడు నిద్రపోకండి, 1980లలో మీ సమస్యను ఎవరైనా పరిష్కరించి ఉండవచ్చు;
  • gnu parallel - ఇది ఒక మాయా విషయం, ప్రతి ఒక్కరూ దీనిని ఉపయోగించాలి;
  • స్పార్క్ కంప్రెస్డ్ డేటాను ఇష్టపడుతుంది మరియు విభజనలను కలపడం ఇష్టం లేదు;
  • సాధారణ సమస్యలను పరిష్కరించేటప్పుడు స్పార్క్ చాలా ఓవర్ హెడ్ కలిగి ఉంటుంది;
  • AWK యొక్క అనుబంధ శ్రేణులు చాలా సమర్థవంతంగా ఉంటాయి;
  • మీరు సంప్రదించవచ్చు stdin и stdout R స్క్రిప్ట్ నుండి, అందువల్ల పైప్‌లైన్‌లో దాన్ని ఉపయోగించండి;
  • స్మార్ట్ మార్గం అమలుకు ధన్యవాదాలు, S3 అనేక ఫైల్‌లను ప్రాసెస్ చేయగలదు;
  • సమయం వృధా కావడానికి ప్రధాన కారణం మీ నిల్వ పద్ధతిని ముందుగానే ఆప్టిమైజ్ చేయడం;
  • పనులను మాన్యువల్‌గా ఆప్టిమైజ్ చేయడానికి ప్రయత్నించవద్దు, కంప్యూటర్ దీన్ని చేయనివ్వండి;
  • వాడుకలో సౌలభ్యం మరియు సౌలభ్యం కోసం API సరళంగా ఉండాలి;
  • మీ డేటా బాగా సిద్ధమైనట్లయితే, కాషింగ్ సులభం అవుతుంది!

మూలం: www.habr.com

ఒక వ్యాఖ్యను జోడించండి