আমার স্ন্যাপের প্রতিক্রিয়াটি এমনটি হতে পারে awk
তবে আপনি যদি প্রচুর লাইনগুলি প্রক্রিয়াকরণ করে থাকেন - এবং আমি কয়েক মিলিয়ন লোকের কথা বলছি - আপনি সম্ভবত "আসল" প্রোগ্রামিং ভাষায় স্যুইচ করে আসল উপকার পাবেন।
এই বিষয়টি মাথায় রেখে (এবং awk
ইতিমধ্যে উত্তর হিসাবে নেওয়া হচ্ছে) আমি বিভিন্ন ভাষায় কয়েকটি বাস্তবায়ন লিখেছি এবং একটি পিসিআই-ই এসএসডি-তে একই 10,000-লাইনের ডেটাসেটে তাদের বেঞ্চমার্ক করেছি।
me* (C) 0m1.734s
me (C++) 0m1.991s
me (Python/Pypy) 0m2.390s
me (perl) 0m3.024s
Thor+Glenn (sed|sh) 0m3.353s
me (python) 0m3.359s
jasonwryan+Thor (awk) 0m3.779s
rush (while read) 0m6.011s
Thor (sed) 1m30.947s
me (parallel) 4m9.429s
এক নজরে সি সবচেয়ে ভাল দেখায় তবে দ্রুত চালাতে পুকুরটি শূকর। আপনি বহু বিলিয়ন লাইনের কথা না বললে পাইপি এবং সি ++ যথেষ্ট ভাল লেখা এবং সম্পাদন করা অনেক সহজ । যদি তা হয়ে থাকে তবে র্যামে বা এসএসডি-তে এই সমস্ত কিছু করার একটি আপগ্রেড কোডের উন্নতির চেয়ে ভাল বিনিয়োগ হতে পারে।
স্পষ্টতই আমি এইগুলির মধ্য দিয়ে যাবার সময়টি আপনি সম্ভবত সবচেয়ে ধীর বিকল্পে কয়েকশ মিলিয়ন রেকর্ড প্রক্রিয়া করতে পারেন । আপনি যদি কেবল লিখতে awk
বা বাশ লুপ করতে পারেন তবে তা করুন এবং জীবন নিয়ে চলুন। আমার স্পষ্টতই আজ অতিরিক্ত সময় ছিল।
আমি কয়েকটি মাল্টি-থ্রেডেড অপশন (সি ++ এবং পাইথন এবং জিএনইউ সহ হাইব্রিডগুলিতেও parallel
) পরীক্ষা করেছিলাম তবে থ্রেডের ওভারহেড এই জাতীয় অপারেশনের (স্ট্রিং স্প্লিটিং, রাইটিং) সম্পূর্ণরূপে কোনও উপকারকে ছাড়িয়ে যায়।
পার্ল
awk
( gawk
এখানে) এই জাতীয় ডেটা পরীক্ষার জন্য সত্যই আমার কলটির প্রথম পোর্ট হবে তবে আপনি পার্লে মোটামুটি একই জিনিস করতে পারেন। অনুরূপ সিনট্যাক্স তবে কিছুটা ভাল লেখার হ্যান্ডেল সহ।
perl -ane 'open(my $fh, ">", $F[0].".seq"); print $fh $F[1]; close $fh;' infile
পাইথন
আমি পাইথন পছন্দ করি । এটি আমার দিনের কাজের ভাষা এবং এটি কেবল একটি দুর্দান্ত, কঠিন এবং অবিশ্বাস্যভাবে পাঠযোগ্য ভাষা। এমনকি একটি শিক্ষানবিস সম্ভবত অনুমান করতে পারে এখানে কী ঘটছে।
with open("infile", "r") as f:
for line in f:
id, chunk = line.split()
with open(id + ".seq", "w") as fw:
fw.write(chunk)
আপনাকে মনে রাখতে হবে যে আপনার বিতরণের python
বাইনারি কেবল পাইথনের বাস্তবায়ন নয়। আমি যখন পাইপির মাধ্যমে এই একই পরীক্ষাটি চালিয়েছি তখন আর কোনও যুক্তি অপ্টিমাইজেশন ছাড়াই এটি সি এর চেয়ে দ্রুত ছিল । পাইথনকে "ধীর ভাষা" হিসাবে লেখার আগে এটি মনে রাখবেন।
সি
আমি আমার সিপিইউটি আসলে কী পেতে পারি তা দেখার জন্য আমি এই উদাহরণটি শুরু করেছিলাম তবে খোলামেলাভাবে, সি যদি আপনি একটি দীর্ঘ সময়ের মধ্যে এটি স্পর্শ না করেন তবে কোড কোডের জন্য দুঃস্বপ্ন। এটি 100-চর লাইনগুলিতে সীমাবদ্ধ হওয়ার অতিরিক্ত যুক্তি রয়েছে যদিও এটি প্রসারিত করা খুব সহজ, আমার কেবল এটির দরকার ছিল না।
আমার আসল সংস্করণটি সি ++ এবং পাইপির চেয়ে ধীর ছিল তবে এটি ব্লগ করার পরে আমি জুলিয়ান ক্লোডের কাছ থেকে কিছুটা সহায়তা পেয়েছি । এই সংস্করণটি এখন দ্রুততর হয়েছে কারণ এটির টুইটকৃত আইও বাফারগুলির কারণে। এটি অন্য যে কোনও কিছুর চেয়েও অনেক দীর্ঘ এবং জড়িত।
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#define BUFLEN (8 * 1024)
int main(void) {
FILE *fp;
FILE *fpout;
char line[100];
char *id;
char *token;
char *buf = malloc(BUFLEN);
fp = fopen("infile", "r");
setvbuf ( fp , buf , _IOLBF, BUFLEN );
while (fgets(line, 100, fp) != NULL) {
id = strtok(line, "\t");
token = strtok(NULL, "\t");
char *fnout = malloc(strlen(id)+5);
fnout = strcat(fnout, id);
fnout = strcat(fnout, ".seq");
fpout = fopen(fnout, "w");
setvbuf ( fpout , NULL , _IONBF , 0 );
fprintf(fpout, "%s", token);
fclose(fpout);
}
fclose(fp);
return 0;
}
সি ++
রিয়েল সি এর চেয়ে ভাল পারফর্ম করে এবং লিখতে অনেক সহজ আপনার কাছে এমন সমস্ত ধরণের জিনিস রয়েছে যা আপনার হাত ধরে থাকে (বিশেষত যখন স্ট্রিং এবং ইনপুট আসে)। এর অর্থ আপনি যুক্তিটি নিখরচায় সহজ করতে পারেন। strtok
সি তে একটি হোগ কারণ এটি পুরো স্ট্রিংটি প্রক্রিয়া করে এবং তারপরে আমাদের সেই ক্লান্তিকর মেমরির বরাদ্দ করতে হবে। এটি কেবল রেখার সাথে সাথে ফ্লিট হয় যতক্ষণ না এটি ট্যাবটি হিট করে এবং সেগমেন্টগুলি আমাদের প্রয়োজন হিসাবে টানতে পারে।
#include <fstream>
#include <string>
using namespace std;
int main(void) {
ifstream in("infile");
ofstream out;
string line;
while(getline(in, line)) {
string::size_type tab = line.find('\t', 0);
string filename = line.substr(0, tab) + ".seq";
out.open(filename.c_str());
out << line.substr(tab + 1);
out.close();
}
in.close();
}
জিএনইউ সমান্তরাল
(মুর্টিল সংস্করণ নয়)। এটি একটি দুর্দান্ত সংক্ষিপ্ত বাক্য গঠন তবে ওএমজিএসএলও। আমি এটি ভুল ব্যবহার করা হতে পারে।
parallel --colsep '\t' echo {2} \> {1}.seq <infile
পরীক্ষার জোতা জেনারেটর
[এটিজিসি] * 64 এর 100000 লাইনের জন্য আমার ডেটা জেনারেটরটি এখানে। এটি দ্রুত নয় এবং উন্নতিগুলি খুব স্বাগত।
cat /dev/urandom | tr -dc 'ATGC' | fold -w 64 | awk 'NR>100000{exit}{printf NR"\t"$0"\n"}' > infile
awk
দশ লক্ষ লক্ষের চেয়ে কম কোনও কিছুর জন্য এখনও উত্তম উত্তর। এমনকি যদি আপনি [রৈখিকভাবে] এটি এক বিলিয়ন লাইন পর্যন্ত স্কেল করেন তবে সি আপনাকে পার্লের চেয়ে 1.5 ঘন্টা এবং আরও বেশি সময় অবধি 3.6 ঘন্টা সাশ্রয় করে।