د AWK او R په کارولو سره 25TB پارس کول

د AWK او R په کارولو سره 25TB پارس کول
دا مقاله څنګه ولولئ: بخښنه غواړم چې متن دومره اوږد او ګډوډ و. ستاسو د وخت خوندي کولو لپاره، زه هر څپرکی د "هغه څه چې ما زده کړل" سره پیل کوم، کوم چې په یوه یا دوه جملو کې د څپرکي جوهر لنډیز کوي.

"یوازې ماته د حل لاره وښایاست!" که تاسو یوازې غواړئ وګورئ چې زه له کوم ځای څخه راغلی یم ، نو فصل ته لاړشئ "ډیر اختراع کونکي کیدل" مګر زما په اند د ناکامۍ په اړه لوستل خورا په زړه پوري او ګټور دي.

ما په دې وروستیو کې د خام DNA ترتیبونو لوی مقدار پروسس کولو لپاره د پروسې تنظیم کولو دنده سپارلې وه (په تخنیکي ډول یو SNP چپ). اړتیا دا وه چې د راتلونکي ماډلینګ او نورو دندو لپاره د ورکړل شوي جنیټیک موقعیت په اړه ژر تر ژره معلومات ترلاسه کړئ (د SNP په نوم یادیږي). د R او AWK په کارولو سره، زه توانیدلی وم چې معلومات په طبیعي ډول پاک او تنظیم کړم، د پوښتنو پروسس کولو خورا ګړندی کول. دا زما لپاره اسانه نه و او ډیری تکرارونو ته اړتیا وه. دا مقاله به تاسو سره زما د ځینو غلطیو څخه مخنیوي کې مرسته وکړي او تاسو ته وښیې چې ما څه پای ته رسولي.

لومړی، ځینې ابتدايي توضیحات.

معلومات

زموږ د پوهنتون د جنیټیک معلوماتو پروسس کولو مرکز موږ ته د 25 TB TSV په بڼه ډاټا چمتو کړې. ما دوی ترلاسه کړل چې په 5 کڅوړو ویشل شوي، د Gzip لخوا فشار شوي، چې هر یو یې شاوخوا 240 څلور ګیګابایټ فایلونه لري. په هر قطار کې د یو فرد څخه د یو SNP لپاره ډاټا شتون لري. په ټولیز ډول، د ~ 2,5 ملیون SNPs او ~ 60 زره خلکو معلومات لیږدول شوي. د SNP معلوماتو سربیره، فایلونه ډیری کالمونه لري چې شمیرې یې مختلف ځانګړتیاوې منعکس کوي، لکه د لوستلو شدت، د مختلفو ایلیلونو فریکونسۍ، او نور. په مجموع کې شاوخوا 30 کالمونه د ځانګړي ارزښتونو سره وو.

هدف

لکه څنګه چې د هرې ډاټا مدیریت پروژې سره، ترټولو مهمه خبره دا وه چې معلومه کړي چې ډاټا به څنګه کارول کیږي. په دې صورت کې موږ به اکثرا د SNP پراساس د SNP لپاره ماډلونه او کاري جریان غوره کړو. دا دی، موږ به په یو وخت کې یوازې په یو SNP کې ډاټا ته اړتیا ولرو. زه باید زده کړم چې څنګه د 2,5 ملیون SNPs څخه یو پورې تړلي ټول ریکارډونه بیرته ترلاسه کړم څومره چې امکان لري په اسانۍ سره ، ګړندي او ارزانه.

دا څنګه نه کول

د یو مناسب کلیچ حواله کولو لپاره:

زه زر ځله ناکامه نه شوم، ما یوازې د پوښتنې دوستانه ب formatه کې د ډیټا د یوې ډلې د پارس کولو څخه مخنیوي لپاره زر لارې موندلې.

لومړی هڅه وکړئ

ما څه زده کړل: په یو وخت کې د 25 TB پارس کولو لپاره کومه ارزانه لاره نشته.

د وانډربیلټ پوهنتون کې "د لوی ډیټا پروسس کولو پرمختللي میتودونه" کورس اخیستو سره ، زه ډاډه وم چې چال په کڅوړه کې و. دا به شاید یو ساعت یا دوه وخت ونیسي چې د Hive سرور تنظیم کړي ترڅو د ټولو معلوماتو له لارې پرمخ بوځي او پایلې راپور کړي. څرنګه چې زموږ معلومات په AWS S3 کې زیرمه شوي، ما خدمت کارولی ایتینا، کوم چې تاسو ته اجازه درکوي د S3 ډیټا ته د Hive SQL پوښتنې پلي کړئ. تاسو اړتیا نلرئ د Hive کلستر تنظیم / پورته کړئ، او تاسو یوازې د هغه معلوماتو لپاره پیسې ورکوئ چې تاسو یې په لټه کې یاست.

وروسته له دې چې ما اتینا زما ډاټا او د هغې بڼه وښودله، ما د دې په څیر پوښتنو سره ځینې ازموینې ترسره کړې:

select * from intensityData limit 10;

او ژر تر ژره ښه جوړ شوي پایلې ترلاسه کړې. چمتو.

تر هغه چې موږ هڅه وکړه چې زموږ په کار کې ډاټا وکاروو ...

له ما څخه وغوښتل شول چې د ماډل ازموینې لپاره ټول SNP معلومات وباسم. ما پوښتنه وکړه:


select * from intensityData 
where snp = 'rs123456';

... او انتظار یې پیل کړ. د اتو دقیقو وروسته او له 4 TB څخه ډیر غوښتل شوي ډیټا ، ما پایله ترلاسه کړه. د موندل شوي ډیټا حجم له مخې ایتینا چارج کوي، په هر ټیرابایټ $ 5. نو دا یوه غوښتنه $ 20 او اته دقیقې انتظار لګښت لري. په ټولو ډیټا کې د ماډل چلولو لپاره، موږ باید 38 کاله انتظار وکړو او 50 ملیون ډالر تادیه کړو. په ښکاره ډول، دا زموږ لپاره مناسب نه و.

دا اړینه وه چې پارکیټ وکاروئ ...

ما څه زده کړل: ستاسو د پارکیټ فایلونو اندازې او د دوی تنظیم سره محتاط اوسئ.

ما لومړی هڅه وکړه چې د ټولو TSVs په بدلولو سره وضعیت سم کړم د پارکیټونو فایلونه. دوی د لوی ډیټا سیټونو سره کار کولو لپاره مناسب دي ځکه چې په دوی کې معلومات د کالم په شکل کې زیرمه شوي: هر کالم په خپله حافظه / ډیسک برخه کې پروت دی ، د متن فایلونو برعکس ، په کوم کې چې قطارونه د هر کالم عناصر لري. او که تاسو اړتیا لرئ یو څه ومومئ، نو یوازې اړین کالم ولولئ. سربیره پردې، هر فایل په کالم کې د ارزښتونو لړۍ ذخیره کوي، نو که هغه ارزښت چې تاسو یې په لټه کې یاست د کالم په حد کې نه وي، سپارک به د ټول فایل سکین کولو وخت ضایع نکړي.

ما یو ساده کار ترسره کړ د AWS گلو د دې لپاره چې زموږ TSVs پارکیټ ته واړوو او نوي فایلونه اتینا ته واړوو. دا شاوخوا 5 ساعته وخت ونیو. مګر کله چې ما غوښتنه ترسره کړه، دا د بشپړولو لپاره ورته وخت او لږې لږې پیسې ونیولې. حقیقت دا دی چې سپارک، د دندې د ښه کولو هڅه کوي، په ساده ډول د TSV یوه ټوټه پاکه کړه او په خپل پارکیټ ټوټه کې یې واچوله. او ځکه چې هره برخه دومره لویه وه چې د ډیری خلکو ټول ریکارډونه ولري، هر فایل ټول SNPs لري، نو سپارک باید ټول فایلونه خلاص کړي ترڅو هغه معلومات راوباسي چې ورته اړتیا وي.

په زړه پورې خبره دا ده چې د پارکیوټ ډیفالټ (او وړاندیز شوی) کمپریشن ډول ، تیز ، د ویشلو وړ ندی. له همدې امله ، هر اجرا کونکی د بشپړ 3,5 GB ډیټاسیټ د پیک کولو او ډاونلوډ کولو دنده کې ودرول شو.

د AWK او R په کارولو سره 25TB پارس کول

راځئ چې ستونزه درک کړو

ما څه زده کړل: ترتیب کول ستونزمن دي، په ځانګړې توګه که چیرې معلومات ویشل شوي وي.

ماته داسې بریښي چې اوس زه د ستونزې په ماهیت پوهیدم. ما یوازې د SNP کالم لخوا ډاټا ترتیب کولو ته اړتیا درلوده، نه د خلکو لخوا. بیا به ډیری SNPs په جلا ډیټا ټوټه کې زیرمه شي ، او بیا د پارکیټ "سمارټ" فنکشن "یوازې خلاصیږي که ارزښت په حد کې وي" به ځان په خپل ټول ویاړ کې وښیې. له بده مرغه، په کلستر کې ویشل شوي ملیاردونو قطارونو ترتیب کول یو ستونزمن کار ثابت شو.

AWS حتما نه غواړي د "زه یو ګډوډي زده کونکی یم" دلیل له امله بیرته ستنیدنه جاري کړي. وروسته له هغه چې زه په ایمیزون ګلو کې ترتیب کولو ته ورغلم ، دا د 2 ورځو لپاره وخوځېد او ټکر شو.

د ویش په اړه څه؟

ما څه زده کړل: په سپارک کې برخې باید متوازن وي.

بیا زه په کروموزومونو کې د ډیټا ویشلو مفکورې سره راغلم. له دوی څخه 23 شتون لري (او څو نور که تاسو د مایټوکونډریال DNA او غیر نقشه شوي سیمې په پام کې ونیسئ).
دا به تاسو ته اجازه درکړي چې معلومات په کوچنیو ټوټو ویشئ. که تاسو په ګلو سکریپټ کې د سپارک صادراتو فنکشن ته یوازې یوه کرښه اضافه کړئ partition_by = "chr"بیا معلومات باید په بالټونو ویشل شي.

د AWK او R په کارولو سره 25TB پارس کول
جینوم د ډیری برخو څخه جوړ دی چې کروموزوم نومیږي.

له بده مرغه، دا کار ونه کړ. کروموزوم مختلف اندازې لري، پدې معنی چې د معلوماتو مختلف مقدار دی. دا پدې مانا ده چې هغه دندې چې سپارک کارګرانو ته لیږلي متوازن ندي او ورو بشپړ شوي ځکه چې ځینې نوډونه دمخه پای ته رسیدلي او بې کاره وو. په هرصورت، دندې بشپړې شوې. مګر کله چې د یو SNP غوښتنه کول ، عدم توازن بیا ستونزې رامینځته کړې. په لویو کروموزومونو کې د SNPs پروسس کولو لګښت (دا هغه ځای دی چیرې چې موږ غواړو معلومات ترلاسه کړو) یوازې د 10 فکتورونو لخوا کم شوی. ډیر، مګر کافي ندي.

که موږ دا حتی په کوچنیو برخو وویشو څه به وي؟

ما څه زده کړل: هیڅکله هڅه مه کوئ چې د 2,5 ملیون پارټیشنونه ترسره کړئ.

ما پریکړه وکړه چې ټول لاړ شم او هر SNP تقسیم کړم. دا یقیني کړه چې ویشونه د مساوي اندازې وو. دا یوه بده مفکوره وه. ما ګلو کارولی او یو بې ګناه کرښه یې اضافه کړه partition_by = 'snp'. دنده یې پیل کړه او اجرا یې پیل کړه. یوه ورځ وروسته ما معاینه کړه او ویې لیدل چې S3 ته لاهم هیڅ نه دی لیکل شوی، نو ما دنده ووژله. داسې ښکاري چې ګلو په S3 کې پټ ځای ته منځمهاله فایلونه لیکي، ډیری فایلونه، شاید یو څو ملیون. د پایلې په توګه، زما غلطۍ د زرو ډالرو څخه ډیر لګښت درلود او زما لارښود خوښ نه کړ.

تقسیم کول + ترتیب کول

ما څه زده کړل: ترتیب کول لاهم ستونزمن دي، لکه څنګه چې د سپارک سره سمون لري.

د ویشلو په برخه کې زما وروستۍ هڅه د کروموزومونو ویشل او بیا د هرې برخې ترتیب کول شامل وو. په تیوري کې، دا به هره پوښتنه ګړندۍ کړي ځکه چې د مطلوب SNP ډیټا باید په ټاکل شوي حد کې د څو پارکیټونو په مینځ کې وي. له بده مرغه، حتی د ویشل شوي ډاټا ترتیب کول یو ستونزمن کار و. د پایلې په توګه، ما د ګمرک کلستر لپاره EMR ته لاړ او اته پیاوړي مثالونه (C5.4xl) او سپارکلیر کارولی ترڅو ډیر انعطاف وړ کاري فلو رامینځته کړي ...

# 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، او نور. مګر ستونزه دا ده چې SNPs په مساوي ډول د کروموزومونو په اوږدو کې نه ویشل شوي، نو له همدې امله د ګروپ اندازه به خورا توپیر ولري.

د AWK او R په کارولو سره 25TB پارس کول

د پایلې په توګه، زه په کټګوریو (درجه) کې د پوستونو ماتولو ته راغلم. د دمخه ډاونلوډ شوي ډیټا په کارولو سره ، ما د ځانګړي SNPs ، د دوی موقعیتونو او کروموزومونو لیست ترلاسه کولو غوښتنه وکړه. بیا ما ډاټا په هر کروموزوم کې ترتیب کړه او SNPs یې د ټاکل شوي اندازې ګروپونو (بن) کې راټول کړل. راځئ چې هر یو 1000 SNPs ووایو. دې ما ته د SNP-to-group-per-chromosome اړیکه راکړه.

په پای کې، ما د 75 SNPs ګروپونه (بن) جوړ کړل، دلیل به یې لاندې تشریح شي.

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 اضافه کول

ما څه زده کړل: کله چې تاسو ته اساسات درکول کیږي خوب مه کوئ. یقینا یو چا دمخه ستاسو ستونزه په 1980s کې حل کړې.

تر دې وخته، د سپارک سره زما د ټولو ناکامیو دلیل په کلستر کې د معلوماتو ګډوډي وه. شاید وضعیت د مخکې درملنې سره ښه شي. ما پریکړه وکړه چې د خام متن ډیټا د کروموزوم کالمونو کې ویشلو هڅه وکړم، نو ما هیله درلوده چې سپارک د "مخکې ویشل شوي" ډاټا سره چمتو کړم.

ما په StackOverflow کې پلټنه وکړه چې څنګه د کالم ارزښتونو سره ویشل او وموندل دومره عالي ځواب. د AWK سره تاسو کولی شئ د متن فایل د کالم ارزښتونو له مخې په سکریپټ کې لیکلو سره تقسیم کړئ نه دا چې پایلې یې واستوئ stdout.

ما د دې هڅه کولو لپاره د باش سکریپټ لیکلی. یو له بسته شوي TSVs ډاونلوډ کړئ ، بیا یې په کارولو سره خلاص کړئ 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په یونیکس کې د ملټي ریډینګ پلي کولو لپاره خورا انعطاف وړ میتود.

د AWK او R په کارولو سره 25TB پارس کول
کله چې ما د نوي پروسې په کارولو سره تقسیم کول پیل کړل ، هرڅه سم وو ، مګر لاهم یو خنډ شتون درلود - ډیسک ته د 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' ذکر کړي. افسوس.

د نوي تجزیه شوي معلوماتو کارول

ما څه زده کړل: سپارک غیر کمپریس شوي ډیټا خوښوي او د برخو ترکیب کول نه خوښوي.

اوس ډاټا په S3 کې په غیر پیک شوي (لوستل: شریک شوي) او نیمه ترتیب شوي بڼه کې وه، او زه کولی شم بیرته سپارک ته راستون شم. یو حیرانتیا زما په تمه وه: زه بیا د هغه څه په ترلاسه کولو کې پاتې راغلم چې ما غوښتل! دا ډیره ستونزمنه وه چې سپارک ته ووایاست چې ډاټا څنګه ویشل شوې وه. او حتی کله چې ما دا وکړل، دا معلومه شوه چې ډیری برخې شتون لري (95 زره)، او کله چې ما کارولې coalesce د دوی شمیر مناسب حد ته راټیټ کړ، دې زما ویش ویجاړ کړ. زه ډاډه یم چې دا حل کیدی شي، مګر د څو ورځو لټون وروسته ما د حل لاره ونه موندله. ما په نهایت کې په سپارک کې ټولې دندې پای ته ورسولې، که څه هم دا یو څه وخت ونیو او زما د ویشلو پارکیټ فایلونه خورا کوچني نه وو (~ 200 KB). په هرصورت، ډاټا هغه ځای و چې ورته اړتیا وه.

د AWK او R په کارولو سره 25TB پارس کول
ډیر کوچنی او نا مساوی، په زړه پوری!

د محلي سپارک پوښتنو ازموینه

ما څه زده کړل: سپارک د ساده ستونزو د حل کولو په وخت کې ډیر سر لري.

په هوښیار شکل کې د ډیټا ډاونلوډ کولو سره ، ما د دې وړتیا درلوده چې سرعت معاینه کړم. د محلي سپارک سرور چلولو لپاره د R سکریپټ تنظیم کړئ، او بیا د ټاکل شوي پارکیټ ګروپ ذخیره (بن) څخه د سپارک ډیټا چوکاټ پورته کړئ. ما هڅه وکړه چې ټول معلومات پورته کړم مګر د ویشلو پیژندلو لپاره سپارکلیر ترلاسه نکړم.

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 GB څخه ډیر حافظه ډیټا سیټ ته ځانګړې کړې چې وزن یې له 15 څخه کم وي.

بېرته AWK ته وگرځه

ما څه زده کړل: په AWK کې ملګري صفونه خورا اغیزمن دي.

زه پوهیدم چې زه کولی شم لوړ سرعت ترلاسه کړم. ما هغه په ​​​​زړه پورې یاد کړ د بروس بارنیټ لخوا د AWK ښوونه ما د یوې ښې ځانګړتیا په اړه لوستل چې نوم یې "ملګری صفونه" په لازمي ډول ، دا د کلیدي ارزښت لرونکي جوړې دي ، کوم چې د یو دلیل لپاره په AWK کې په مختلف ډول ویل شوي ، او له همدې امله ما یو څه د دوی په اړه ډیر فکر نه کاوه. رومن چیپلیکا په یاد ولرئ چې د "ملګرو صفونو" اصطالح د "کلیدي ارزښت جوړه" اصطلاح څخه خورا زوړ دی. حتی که تاسو په ګوګل Ngram کې کلیدي ارزښت وګورئ، تاسو به دا اصطلاح هلته ونه ګورئ، مګر تاسو به ملګري صفونه ومومئ! برسېره پردې، د "کلیدي ارزښت جوړه" ډیری وختونه د ډیټابیسونو سره تړاو لري، نو دا د هش میپ سره پرتله کولو لپاره خورا ډیر معنی لري. ما پوهیده چې زه کولی شم د دې اتحادیې صفونه وکاروم ترڅو زما SNPs د بن میز او خام ډیټا سره د سپارک کارولو پرته شریک کړم.

د دې کولو لپاره، په 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. د پایلې په توګه، ډیری کوچني فایلونه په ډیسک کې رامینځته شوي (د دې لپاره ما د terabyte EBS حجم کارولی دی).

د دویمې برخې څخه لیږدونکی parallel د ګروپونو (بن) څخه تیریږي او د دوی انفرادي فایلونه په عام CSV c کې سره یوځای کوي 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. دا په یوه ګروپ (بن) کې د ټولو ځانګړو SNPs لړۍ ده، تاسو ته اجازه درکوي په چټکۍ سره وګورئ چې ایا تاسو دمخه د پخوانۍ پوښتنې څخه ډاټا لرئ. دا د دې کوډ سره په ګروپ (بن) کې د ټولو SNPs له لارې لوپ کول هم اسانه کوي:

# 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

Add a comment