AWK ಮತ್ತು R ಬಳಸಿಕೊಂಡು 25TB ಪಾರ್ಸಿಂಗ್

AWK ಮತ್ತು R ಬಳಸಿಕೊಂಡು 25TB ಪಾರ್ಸಿಂಗ್
ಈ ಲೇಖನವನ್ನು ಹೇಗೆ ಓದುವುದು: ಪಠ್ಯವು ತುಂಬಾ ಉದ್ದವಾಗಿದೆ ಮತ್ತು ಅಸ್ತವ್ಯಸ್ತವಾಗಿರುವುದಕ್ಕೆ ನಾನು ಕ್ಷಮೆಯಾಚಿಸುತ್ತೇನೆ. ನಿಮ್ಮ ಸಮಯವನ್ನು ಉಳಿಸಲು, ನಾನು ಪ್ರತಿ ಅಧ್ಯಾಯವನ್ನು "ನಾನು ಕಲಿತದ್ದು" ಪರಿಚಯದೊಂದಿಗೆ ಪ್ರಾರಂಭಿಸುತ್ತೇನೆ, ಇದು ಒಂದು ಅಥವಾ ಎರಡು ವಾಕ್ಯಗಳಲ್ಲಿ ಅಧ್ಯಾಯದ ಸಾರವನ್ನು ಸಾರಾಂಶಗೊಳಿಸುತ್ತದೆ.

"ನನಗೆ ಪರಿಹಾರವನ್ನು ತೋರಿಸು!" ನಾನು ಎಲ್ಲಿಂದ ಬಂದಿದ್ದೇನೆ ಎಂದು ನೀವು ನೋಡಲು ಬಯಸಿದರೆ, "ಹೆಚ್ಚು ಇನ್ವೆಂಟಿವ್ ಆಗುತ್ತಿದೆ" ಎಂಬ ಅಧ್ಯಾಯಕ್ಕೆ ತೆರಳಿ, ಆದರೆ ವೈಫಲ್ಯದ ಬಗ್ಗೆ ಓದಲು ಇದು ಹೆಚ್ಚು ಆಸಕ್ತಿದಾಯಕ ಮತ್ತು ಉಪಯುಕ್ತವಾಗಿದೆ ಎಂದು ನಾನು ಭಾವಿಸುತ್ತೇನೆ.

ದೊಡ್ಡ ಪ್ರಮಾಣದ ಕಚ್ಚಾ ಡಿಎನ್‌ಎ ಅನುಕ್ರಮಗಳನ್ನು (ತಾಂತ್ರಿಕವಾಗಿ ಎಸ್‌ಎನ್‌ಪಿ ಚಿಪ್) ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಪ್ರಕ್ರಿಯೆಯನ್ನು ಹೊಂದಿಸಲು ನನಗೆ ಇತ್ತೀಚೆಗೆ ವಹಿಸಲಾಯಿತು. ನಂತರದ ಮಾಡೆಲಿಂಗ್ ಮತ್ತು ಇತರ ಕಾರ್ಯಗಳಿಗಾಗಿ ನೀಡಲಾದ ಆನುವಂಶಿಕ ಸ್ಥಳದ (ಎಸ್‌ಎನ್‌ಪಿ ಎಂದು ಕರೆಯುವ) ಡೇಟಾವನ್ನು ತ್ವರಿತವಾಗಿ ಪಡೆಯುವುದು ಅಗತ್ಯವಾಗಿತ್ತು. 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 ಗಳನ್ನು ಒಳಗೊಂಡಿತ್ತು, ಆದ್ದರಿಂದ ಸ್ಪಾರ್ಕ್ ಅಗತ್ಯವಿರುವ ಮಾಹಿತಿಯನ್ನು ಹೊರತೆಗೆಯಲು ಎಲ್ಲಾ ಫೈಲ್‌ಗಳನ್ನು ತೆರೆಯಬೇಕಾಗಿತ್ತು.

ಕುತೂಹಲಕಾರಿಯಾಗಿ, ಪ್ಯಾರ್ಕ್ವೆಟ್‌ನ ಡೀಫಾಲ್ಟ್ (ಮತ್ತು ಶಿಫಾರಸು ಮಾಡಲಾದ) ಕಂಪ್ರೆಷನ್ ಪ್ರಕಾರ, ಸ್ನ್ಯಾಪಿ, ವಿಭಜನೆಯಾಗುವುದಿಲ್ಲ. ಆದ್ದರಿಂದ, ಪ್ರತಿ ಕಾರ್ಯನಿರ್ವಾಹಕರು ಪೂರ್ಣ 3,5 GB ಡೇಟಾಸೆಟ್ ಅನ್ನು ಅನ್ಪ್ಯಾಕ್ ಮಾಡುವ ಮತ್ತು ಡೌನ್‌ಲೋಡ್ ಮಾಡುವ ಕಾರ್ಯದಲ್ಲಿ ಸಿಲುಕಿಕೊಂಡರು.

AWK ಮತ್ತು R ಬಳಸಿಕೊಂಡು 25TB ಪಾರ್ಸಿಂಗ್

ಸಮಸ್ಯೆಯನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳೋಣ

ನಾನು ಏನು ಕಲಿತಿದ್ದೇನೆ: ವಿಂಗಡಣೆ ಕಷ್ಟ, ವಿಶೇಷವಾಗಿ ಡೇಟಾವನ್ನು ವಿತರಿಸಿದರೆ.

ಈಗ ನಾನು ಸಮಸ್ಯೆಯ ಸಾರವನ್ನು ಅರ್ಥಮಾಡಿಕೊಂಡಿದ್ದೇನೆ ಎಂದು ನನಗೆ ತೋರುತ್ತದೆ. ನಾನು ಡೇಟಾವನ್ನು SNP ಕಾಲಮ್ ಮೂಲಕ ಮಾತ್ರ ವಿಂಗಡಿಸಬೇಕಾಗಿತ್ತು, ಜನರಿಂದ ಅಲ್ಲ. ನಂತರ ಹಲವಾರು SNP ಗಳನ್ನು ಪ್ರತ್ಯೇಕ ಡೇಟಾ ಚಂಕ್ನಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗುತ್ತದೆ, ಮತ್ತು ನಂತರ ಪಾರ್ಕ್ವೆಟ್ನ "ಸ್ಮಾರ್ಟ್" ಕಾರ್ಯವು "ಮೌಲ್ಯವು ವ್ಯಾಪ್ತಿಯಲ್ಲಿದ್ದರೆ ಮಾತ್ರ ತೆರೆಯಿರಿ" ಅದರ ಎಲ್ಲಾ ವೈಭವದಲ್ಲಿ ಸ್ವತಃ ತೋರಿಸುತ್ತದೆ. ದುರದೃಷ್ಟವಶಾತ್, ಕ್ಲಸ್ಟರ್‌ನಲ್ಲಿ ಹರಡಿರುವ ಶತಕೋಟಿ ಸಾಲುಗಳ ಮೂಲಕ ವಿಂಗಡಿಸುವುದು ಕಷ್ಟಕರವಾದ ಕೆಲಸವೆಂದು ಸಾಬೀತಾಯಿತು.

"ನಾನು ವಿಚಲಿತ ವಿದ್ಯಾರ್ಥಿ" ಎಂಬ ಕಾರಣದಿಂದ AWS ಖಂಡಿತವಾಗಿಯೂ ಮರುಪಾವತಿಯನ್ನು ನೀಡಲು ಬಯಸುವುದಿಲ್ಲ. ನಾನು ಅಮೆಜಾನ್ ಗ್ಲೂನಲ್ಲಿ ವಿಂಗಡಿಸಲು ಓಡಿದ ನಂತರ, ಅದು 2 ದಿನಗಳವರೆಗೆ ಓಡಿ ಕ್ರ್ಯಾಶ್ ಆಯಿತು.

ವಿಭಜನೆಯ ಬಗ್ಗೆ ಏನು?

ನಾನು ಏನು ಕಲಿತಿದ್ದೇನೆ: ಸ್ಪಾರ್ಕ್‌ನಲ್ಲಿನ ವಿಭಾಗಗಳು ಸಮತೋಲನದಲ್ಲಿರಬೇಕು.

ನಂತರ ನಾನು ಕ್ರೋಮೋಸೋಮ್‌ಗಳಲ್ಲಿ ಡೇಟಾವನ್ನು ವಿಭಜಿಸುವ ಕಲ್ಪನೆಯೊಂದಿಗೆ ಬಂದಿದ್ದೇನೆ. ಅವುಗಳಲ್ಲಿ 23 ಇವೆ (ಮತ್ತು ನೀವು ಮೈಟೊಕಾಂಡ್ರಿಯದ DNA ಮತ್ತು ಮ್ಯಾಪ್ ಮಾಡದ ಪ್ರದೇಶಗಳನ್ನು ಗಣನೆಗೆ ತೆಗೆದುಕೊಂಡರೆ ಇನ್ನೂ ಹಲವಾರು).
ಡೇಟಾವನ್ನು ಸಣ್ಣ ಭಾಗಗಳಾಗಿ ವಿಭಜಿಸಲು ಇದು ನಿಮ್ಮನ್ನು ಅನುಮತಿಸುತ್ತದೆ. ನೀವು ಅಂಟು ಸ್ಕ್ರಿಪ್ಟ್‌ನಲ್ಲಿ ಸ್ಪಾರ್ಕ್ ರಫ್ತು ಕಾರ್ಯಕ್ಕೆ ಕೇವಲ ಒಂದು ಸಾಲನ್ನು ಸೇರಿಸಿದರೆ partition_by = "chr", ನಂತರ ಡೇಟಾವನ್ನು ಬಕೆಟ್ಗಳಾಗಿ ವಿಂಗಡಿಸಬೇಕು.

AWK ಮತ್ತು R ಬಳಸಿಕೊಂಡು 25TB ಪಾರ್ಸಿಂಗ್
ಜೀನೋಮ್ ಕ್ರೋಮೋಸೋಮ್‌ಗಳೆಂದು ಕರೆಯಲ್ಪಡುವ ಹಲವಾರು ತುಣುಕುಗಳನ್ನು ಒಳಗೊಂಡಿದೆ.

ದುರದೃಷ್ಟವಶಾತ್, ಇದು ಕೆಲಸ ಮಾಡಲಿಲ್ಲ. ವರ್ಣತಂತುಗಳು ವಿಭಿನ್ನ ಗಾತ್ರಗಳನ್ನು ಹೊಂದಿವೆ, ಅಂದರೆ ವಿಭಿನ್ನ ಪ್ರಮಾಣದ ಮಾಹಿತಿ. ಇದರರ್ಥ ಸ್ಪಾರ್ಕ್ ಕೆಲಸಗಾರರಿಗೆ ಕಳುಹಿಸಿದ ಕಾರ್ಯಗಳು ಸಮತೋಲನದಲ್ಲಿರಲಿಲ್ಲ ಮತ್ತು ನಿಧಾನವಾಗಿ ಪೂರ್ಣಗೊಳ್ಳುವುದಿಲ್ಲ ಏಕೆಂದರೆ ಕೆಲವು ನೋಡ್‌ಗಳು ಬೇಗನೆ ಮುಗಿದವು ಮತ್ತು ನಿಷ್ಕ್ರಿಯವಾಗಿದ್ದವು. ಆದಾಗ್ಯೂ, ಕಾರ್ಯಗಳು ಪೂರ್ಣಗೊಂಡಿವೆ. ಆದರೆ ಒಂದು SNP ಗಾಗಿ ಕೇಳಿದಾಗ, ಅಸಮತೋಲನವು ಮತ್ತೆ ಸಮಸ್ಯೆಗಳನ್ನು ಉಂಟುಮಾಡಿತು. ದೊಡ್ಡ ಕ್ರೋಮೋಸೋಮ್‌ಗಳಲ್ಲಿ (ಅಂದರೆ, ನಾವು ಡೇಟಾವನ್ನು ಪಡೆಯಲು ಬಯಸುವ) SNP ಗಳನ್ನು ಸಂಸ್ಕರಿಸುವ ವೆಚ್ಚವು ಸುಮಾರು 10 ಅಂಶಗಳಷ್ಟು ಕಡಿಮೆಯಾಗಿದೆ. ಬಹಳಷ್ಟು, ಆದರೆ ಸಾಕಾಗುವುದಿಲ್ಲ.

ನಾವು ಅದನ್ನು ಇನ್ನೂ ಸಣ್ಣ ಭಾಗಗಳಾಗಿ ವಿಂಗಡಿಸಿದರೆ ಏನು?

ನಾನು ಏನು ಕಲಿತಿದ್ದೇನೆ: 2,5 ಮಿಲಿಯನ್ ವಿಭಾಗಗಳನ್ನು ಮಾಡಲು ಎಂದಿಗೂ ಪ್ರಯತ್ನಿಸಬೇಡಿ.

ನಾನು ಎಲ್ಲವನ್ನೂ ಹೋಗಲು ನಿರ್ಧರಿಸಿದೆ ಮತ್ತು ಪ್ರತಿ SNP ಅನ್ನು ವಿಭಜಿಸಿದೆ. ವಿಭಾಗಗಳು ಸಮಾನ ಗಾತ್ರದಲ್ಲಿವೆ ಎಂದು ಇದು ಖಚಿತಪಡಿಸಿತು. ಇದು ಒಂದು ಕೆಟ್ಟ ಐಡಿಯಾ ಆಗಿತ್ತು. ನಾನು ಅಂಟು ಬಳಸಿದ್ದೇನೆ ಮತ್ತು ಮುಗ್ಧ ರೇಖೆಯನ್ನು ಸೇರಿಸಿದೆ partition_by = 'snp'. ಕಾರ್ಯವು ಪ್ರಾರಂಭವಾಯಿತು ಮತ್ತು ಕಾರ್ಯಗತಗೊಳಿಸಲು ಪ್ರಾರಂಭಿಸಿತು. ಒಂದು ದಿನದ ನಂತರ ನಾನು ಪರಿಶೀಲಿಸಿದೆ ಮತ್ತು S3 ಗೆ ಇನ್ನೂ ಏನೂ ಬರೆಯಲಾಗಿಲ್ಲ ಎಂದು ನೋಡಿದೆ, ಆದ್ದರಿಂದ ನಾನು ಕೆಲಸವನ್ನು ಕೊಂದಿದ್ದೇನೆ. ಅಂಟು 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, ಯುನಿಕ್ಸ್‌ನಲ್ಲಿ ಮಲ್ಟಿಥ್ರೆಡಿಂಗ್ ಅನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಲು ಬಹಳ ಹೊಂದಿಕೊಳ್ಳುವ ವಿಧಾನ.

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, ಇದು ಜಿಜಿಪ್ ಟೂಲ್ ಆಗಿದ್ದು, ಫೈಲ್‌ಗಳನ್ನು ಡಿಕಂಪ್ರೆಸಿಂಗ್ ಮಾಡುವ ಆರಂಭದಲ್ಲಿ ಸಮಾನಾಂತರವಲ್ಲದ ಕಾರ್ಯವನ್ನು ಸಮಾನಾಂತರಗೊಳಿಸಲು ತಂಪಾದ ಕೆಲಸಗಳನ್ನು ಮಾಡಬಹುದು (ಇದು ಕನಿಷ್ಠ ಸಹಾಯ ಮಾಡಿದೆ).

# 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 ಸ್ಕ್ರಿಪ್ಟ್ ಅನ್ನು ಹೊಂದಿಸಿ, ತದನಂತರ ನಿರ್ದಿಷ್ಟಪಡಿಸಿದ ಪಾರ್ಕ್ವೆಟ್ ಗುಂಪಿನ ಸಂಗ್ರಹಣೆಯಿಂದ (ಬಿನ್) ಸ್ಪಾರ್ಕ್ ಡೇಟಾ ಫ್ರೇಮ್ ಅನ್ನು ಲೋಡ್ ಮಾಡಿ. ನಾನು ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಲೋಡ್ ಮಾಡಲು ಪ್ರಯತ್ನಿಸಿದೆ ಆದರೆ ವಿಭಜನೆಯನ್ನು ಗುರುತಿಸಲು 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 GB ಗಿಂತ ಹೆಚ್ಚು ಮೆಮೊರಿಯನ್ನು 15 ಕ್ಕಿಂತ ಕಡಿಮೆ ತೂಕದ ಡೇಟಾಸೆಟ್‌ಗೆ ನಿಯೋಜಿಸಿದಾಗಲೂ ಸಹ.

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, ಇದು ನಿರ್ದಿಷ್ಟಪಡಿಸಿದ ಸ್ಟ್ರೀಮ್‌ಗೆ ಕಳುಹಿಸುವ ಯಾವುದೇ ಡೇಟಾವನ್ನು ನೇರವಾಗಿ ಆಜ್ಞೆಗೆ ಸೇರಿಸುತ್ತದೆ. ಆಯ್ಕೆ {#} ಅನನ್ಯ ಥ್ರೆಡ್ ಐಡಿಯನ್ನು ಒದಗಿಸುತ್ತದೆ, ಮತ್ತು {%} ಕೆಲಸದ ಸ್ಲಾಟ್ ಸಂಖ್ಯೆಯನ್ನು ಪ್ರತಿನಿಧಿಸುತ್ತದೆ (ಪುನರಾವರ್ತಿತ, ಆದರೆ ಏಕಕಾಲದಲ್ಲಿ ಎಂದಿಗೂ). ಎಲ್ಲಾ ಆಯ್ಕೆಗಳ ಪಟ್ಟಿಯನ್ನು ಕಾಣಬಹುದು ದಸ್ತಾವೇಜನ್ನು.

#!/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 ನ ಭಾಗಗಳು ಹೆಚ್ಚು ಆಪ್ಟಿಮೈಸ್ ಆಗಿರುವುದು ಆಶ್ಚರ್ಯವೇನಿಲ್ಲ. ಒಂದು ಮಧ್ಯಮ ಗಾತ್ರದ ಕ್ರೋಮೋಸೋಮ್ ಅನ್ನು ಪರೀಕ್ಷಿಸಿದ ನಂತರ, ಕೆಲಸವು ಸುಮಾರು ಎರಡು ಗಂಟೆಗಳಲ್ಲಿ C5n.4xl ನಿದರ್ಶನದಲ್ಲಿ ಪೂರ್ಣಗೊಂಡಿತು.

S3 ಮಿತಿಗಳು

ನಾನು ಏನು ಕಲಿತಿದ್ದೇನೆ: ಸ್ಮಾರ್ಟ್ ಪಾತ್ ಅನುಷ್ಠಾನಕ್ಕೆ ಧನ್ಯವಾದಗಳು, S3 ಅನೇಕ ಫೈಲ್‌ಗಳನ್ನು ನಿಭಾಯಿಸಬಲ್ಲದು.

S3 ಗೆ ವರ್ಗಾವಣೆಗೊಂಡ ಅನೇಕ ಫೈಲ್‌ಗಳನ್ನು ನಿಭಾಯಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತದೆಯೇ ಎಂದು ನಾನು ಚಿಂತೆ ಮಾಡುತ್ತಿದ್ದೆ. ನಾನು ಫೈಲ್ ಹೆಸರುಗಳನ್ನು ಅರ್ಥಪೂರ್ಣವಾಗಿ ಮಾಡಬಹುದು, ಆದರೆ S3 ಅವರಿಗೆ ಹೇಗೆ ಕಾಣುತ್ತದೆ?

AWK ಮತ್ತು R ಬಳಸಿಕೊಂಡು 25TB ಪಾರ್ಸಿಂಗ್
S3 ನಲ್ಲಿನ ಫೋಲ್ಡರ್‌ಗಳು ಕೇವಲ ಪ್ರದರ್ಶನಕ್ಕಾಗಿ ಮಾತ್ರ, ವಾಸ್ತವವಾಗಿ ಸಿಸ್ಟಂ ಚಿಹ್ನೆಯಲ್ಲಿ ಆಸಕ್ತಿ ಹೊಂದಿಲ್ಲ /. S3 FAQ ಪುಟದಿಂದ.

S3 ನಿರ್ದಿಷ್ಟ ಫೈಲ್‌ಗೆ ಮಾರ್ಗವನ್ನು ಒಂದು ರೀತಿಯ ಹ್ಯಾಶ್ ಟೇಬಲ್ ಅಥವಾ ಡಾಕ್ಯುಮೆಂಟ್-ಆಧಾರಿತ ಡೇಟಾಬೇಸ್‌ನಲ್ಲಿ ಸರಳ ಕೀಲಿಯಾಗಿ ಪ್ರತಿನಿಧಿಸುತ್ತದೆ ಎಂದು ತೋರುತ್ತಿದೆ. ಬಕೆಟ್ ಅನ್ನು ಟೇಬಲ್ ಎಂದು ಪರಿಗಣಿಸಬಹುದು ಮತ್ತು ಫೈಲ್ಗಳನ್ನು ಆ ಕೋಷ್ಟಕದಲ್ಲಿ ದಾಖಲೆಗಳಾಗಿ ಪರಿಗಣಿಸಬಹುದು.

ಅಮೆಜಾನ್‌ನಲ್ಲಿ ಲಾಭ ಗಳಿಸಲು ವೇಗ ಮತ್ತು ದಕ್ಷತೆಯು ಮುಖ್ಯವಾಗಿರುವುದರಿಂದ, ಈ ಕೀ-ಆಸ್-ಫೈಲ್-ಪಾತ್ ಸಿಸ್ಟಮ್ ಫ್ರೀಕಿಂಗ್ ಆಪ್ಟಿಮೈಸ್ ಆಗಿರುವುದು ಆಶ್ಚರ್ಯವೇನಿಲ್ಲ. ನಾನು ಸಮತೋಲನವನ್ನು ಹುಡುಕಲು ಪ್ರಯತ್ನಿಸಿದೆ: ಇದರಿಂದ ನಾನು ಹೆಚ್ಚಿನ ವಿನಂತಿಗಳನ್ನು ಮಾಡಬೇಕಾಗಿಲ್ಲ, ಆದರೆ ವಿನಂತಿಗಳನ್ನು ತ್ವರಿತವಾಗಿ ಕಾರ್ಯಗತಗೊಳಿಸಲಾಗಿದೆ. ಸುಮಾರು 20 ಸಾವಿರ ಬಿನ್ ಫೈಲ್‌ಗಳನ್ನು ಮಾಡುವುದು ಉತ್ತಮ ಎಂದು ಅದು ಬದಲಾಯಿತು. ನಾವು ಆಪ್ಟಿಮೈಜ್ ಮಾಡುವುದನ್ನು ಮುಂದುವರಿಸಿದರೆ, ನಾವು ವೇಗದಲ್ಲಿ ಹೆಚ್ಚಳವನ್ನು ಸಾಧಿಸಬಹುದು ಎಂದು ನಾನು ಭಾವಿಸುತ್ತೇನೆ (ಉದಾಹರಣೆಗೆ, ಡೇಟಾಕ್ಕಾಗಿ ವಿಶೇಷ ಬಕೆಟ್ ಅನ್ನು ತಯಾರಿಸುವುದು, ಹೀಗಾಗಿ ಲುಕಪ್ ಟೇಬಲ್ನ ಗಾತ್ರವನ್ನು ಕಡಿಮೆ ಮಾಡುವುದು). ಆದರೆ ಮುಂದಿನ ಪ್ರಯೋಗಗಳಿಗೆ ಸಮಯ ಅಥವಾ ಹಣವಿರಲಿಲ್ಲ.

ಅಡ್ಡ ಹೊಂದಾಣಿಕೆಯ ಬಗ್ಗೆ ಏನು?

ನಾನು ಕಲಿತದ್ದು: ನಿಮ್ಮ ಶೇಖರಣಾ ವಿಧಾನವನ್ನು ಅಕಾಲಿಕವಾಗಿ ಉತ್ತಮಗೊಳಿಸುವುದು ವ್ಯರ್ಥ ಸಮಯಕ್ಕೆ ಪ್ರಮುಖ ಕಾರಣವಾಗಿದೆ.

ಈ ಹಂತದಲ್ಲಿ, ನಿಮ್ಮನ್ನು ಕೇಳಿಕೊಳ್ಳುವುದು ಬಹಳ ಮುಖ್ಯ: "ಯಾಕೆ ಸ್ವಾಮ್ಯದ ಫೈಲ್ ಫಾರ್ಮ್ಯಾಟ್ ಅನ್ನು ಬಳಸಬೇಕು?" ಕಾರಣ ಲೋಡಿಂಗ್ ವೇಗ (ಜಿಜಿಪ್ ಮಾಡಿದ 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 ಪ್ಯಾರ್ಕ್ವೆಟ್ ಫೈಲ್‌ಗಳಿಗೆ, ಇದು ನನಗೆ ಸಮಸ್ಯೆಯಾಗಬೇಕು, ನನ್ನ ಸಹೋದ್ಯೋಗಿಗಳಿಗೆ ಅಲ್ಲ. ಇದಕ್ಕಾಗಿ ನಾನು ಆಂತರಿಕ ಆರ್ ಪ್ಯಾಕೇಜ್ ಮಾಡಲು ನಿರ್ಧರಿಸಿದೆ.

ಒಂದು ಕಾರ್ಯದ ಸುತ್ತಲೂ ಆಯೋಜಿಸಲಾದ ಕೆಲವೇ ಡೇಟಾ ಪ್ರವೇಶ ಕಾರ್ಯಗಳನ್ನು ಹೊಂದಿರುವ ಅತ್ಯಂತ ಸರಳವಾದ ಪ್ಯಾಕೇಜ್ ಅನ್ನು ನಿರ್ಮಿಸಿ ಮತ್ತು ದಾಖಲಿಸಿ 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

ಕಾಮೆಂಟ್ ಅನ್ನು ಸೇರಿಸಿ