আমি কিছুটা গতি অর্জন করতে এবং আমার মরিচা সি ++ দক্ষতা তীক্ষ্ণ করার প্রয়াসে পাইথন থেকে কিছু কোড সি ++ তে রূপান্তর করার চেষ্টা করছি। আমি গতকাল মর্মাহত যখন stdin থেকে লাইন পড়া একটি সরল বাস্তবায়ন অনেক দ্রুত সি চেয়ে পাইথন ছিল ++, (দেখুন হয়েছিল এই )। আজ, আমি অবশেষে শিখলাম কীভাবে সি ++ তে একটি স্ট্রিং বিভক্ত করতে হবে ডিলিমিটারগুলিতে (পাইথনের বিভক্তির অনুরূপ শব্দার্থক) (এবং), এবং এখন আমি দেজা ভুতে অনুভব করছি! আমার সি ++ কোডটি কাজটি করতে অনেক বেশি সময় নেয় (যদিও গতকালের পাঠের ক্ষেত্রে এটি আরও বিশালতার অর্ডার নয়)।
পাইথন কোড:
#!/usr/bin/env python
from __future__ import print_function
import time
import sys
count = 0
start_time = time.time()
dummy = None
for line in sys.stdin:
dummy = line.split()
count += 1
delta_sec = int(time.time() - start_time)
print("Python: Saw {0} lines in {1} seconds. ".format(count, delta_sec), end='')
if delta_sec > 0:
lps = int(count/delta_sec)
print(" Crunch Speed: {0}".format(lps))
else:
print('')
সি ++ কোড:
#include <iostream>
#include <string>
#include <sstream>
#include <time.h>
#include <vector>
using namespace std;
void split1(vector<string> &tokens, const string &str,
const string &delimiters = " ") {
// Skip delimiters at beginning
string::size_type lastPos = str.find_first_not_of(delimiters, 0);
// Find first non-delimiter
string::size_type pos = str.find_first_of(delimiters, lastPos);
while (string::npos != pos || string::npos != lastPos) {
// Found a token, add it to the vector
tokens.push_back(str.substr(lastPos, pos - lastPos));
// Skip delimiters
lastPos = str.find_first_not_of(delimiters, pos);
// Find next non-delimiter
pos = str.find_first_of(delimiters, lastPos);
}
}
void split2(vector<string> &tokens, const string &str, char delim=' ') {
stringstream ss(str); //convert string to stream
string item;
while(getline(ss, item, delim)) {
tokens.push_back(item); //add token to vector
}
}
int main() {
string input_line;
vector<string> spline;
long count = 0;
int sec, lps;
time_t start = time(NULL);
cin.sync_with_stdio(false); //disable synchronous IO
while(cin) {
getline(cin, input_line);
spline.clear(); //empty the vector for the next line to parse
//I'm trying one of the two implementations, per compilation, obviously:
// split1(spline, input_line);
split2(spline, input_line);
count++;
};
count--; //subtract for final over-read
sec = (int) time(NULL) - start;
cerr << "C++ : Saw " << count << " lines in " << sec << " seconds." ;
if (sec > 0) {
lps = count / sec;
cerr << " Crunch speed: " << lps << endl;
} else
cerr << endl;
return 0;
//compiled with: g++ -Wall -O3 -o split1 split_1.cpp
মনে রাখবেন যে আমি দুটি পৃথক বিভাজন বাস্তবায়নের চেষ্টা করেছি। ওয়ান (split1) টোকেন জন্য অনুসন্ধান করতে স্ট্রিং পদ্ধতি ব্যবহার করে এবং একাধিক টোকেন সেইসাথে হ্যান্ডেল অসংখ্য টোকেন (এটা থেকে আসে একত্রীকরণ করতে সক্ষম হয় এখানে )। দ্বিতীয় (স্প্লিট 2) স্ট্রিমটি স্ট্রিম হিসাবে পড়তে গেটলাইন ব্যবহার করে, ডিলিমিটারগুলিকে একীভূত করে না এবং কেবল একটি একক ডিলিমিটার অক্ষরকে সমর্থন করে (এটি স্ট্রিং বিভক্ত প্রশ্নের উত্তরগুলির জন্য বেশ কয়েকটি স্ট্যাকওভারফ্লো ব্যবহারকারীরা পোস্ট করেছিলেন)।
আমি বিভিন্ন অর্ডার এ একাধিক বার চালানো। আমার পরীক্ষা মেশিনটি একটি ম্যাকবুক প্রো (২০১১, ৮ জিবি, কোয়াড কোর), এটি যে খুব বেশি গুরুত্বপূর্ণ তা নয়। আমি তিনটি স্পেস-বিভক্ত কলামগুলির সাথে 20 এম লাইন পাঠ্য ফাইলটি পরীক্ষা করছি যা প্রত্যেকে এর সাথে একই রকম দেখাচ্ছে: "foo.bar 127.0.0.1 home.foo.bar"
ফলাফল:
$ /usr/bin/time cat test_lines_double | ./split.py
15.61 real 0.01 user 0.38 sys
Python: Saw 20000000 lines in 15 seconds. Crunch Speed: 1333333
$ /usr/bin/time cat test_lines_double | ./split1
23.50 real 0.01 user 0.46 sys
C++ : Saw 20000000 lines in 23 seconds. Crunch speed: 869565
$ /usr/bin/time cat test_lines_double | ./split2
44.69 real 0.02 user 0.62 sys
C++ : Saw 20000000 lines in 45 seconds. Crunch speed: 444444
আমি কি ভুল করছি? সি ++ তে স্ট্রিং বিভক্ত করার আরও ভাল উপায় কি আছে যা বাহ্যিক গ্রন্থাগারগুলিতে নির্ভর করে না (যেমন কোনও উত্সাহ দেয় না), সীমানা বিহীন ক্রমগুলি (পাইথনের বিভাজনের মতো) সমর্থন করে, থ্রেড নিরাপদ (সুতরাং কোনও স্ট্রোক নেই), এবং যার অভিনয় কমপক্ষে অজগর সমান?
1 / আংশিক সমাধান সম্পাদনা করুন ?:
সি ++ এর মতো আমি অজগরটি ডামি তালিকাটি পুনরায় সেট করে এবং প্রতিবার এটিতে যুক্ত করে আরও সুষ্ঠু তুলনা করার চেষ্টা করেছি। এটি এখনও সি ++ কোডটি ঠিক কী করছে না তবে এটি কিছুটা কাছাকাছি। মূলত, লুপটি এখন:
for line in sys.stdin:
dummy = []
dummy += line.split()
count += 1
পাইথনের পারফরম্যান্স এখন স্প্লিট 1 সি ++ বাস্তবায়নের সমান।
/usr/bin/time cat test_lines_double | ./split5.py
22.61 real 0.01 user 0.40 sys
Python: Saw 20000000 lines in 22 seconds. Crunch Speed: 909090
আমি এখনও অবাক হয়েছি যে, পাইথন স্ট্রিং প্রসেসিংয়ের জন্য এতটাই অনুকূলিত হয়ে উঠেছে (ম্যাট জয়েন্টার যেমন প্রস্তাব করেছে), এই সি ++ বাস্তবায়ন দ্রুততর হবে না। সি ++ ব্যবহার করে আরও অনুকূল উপায়ে কীভাবে এটি করা যায় সে সম্পর্কে কারও ধারনা থাকলে দয়া করে আপনার কোডটি ভাগ করুন। (আমি মনে করি যে আমার পরবর্তী পদক্ষেপটি খাঁটি সিতে এটি প্রয়োগের চেষ্টা করবে, যদিও আমি সিটিতে আমার সামগ্রিক প্রকল্পটি পুনরায় বাস্তবায়ন করতে প্রোগ্রামার উত্পাদনশীলতা বাণিজ্য করতে যাচ্ছি না, সুতরাং এটি কেবল স্ট্রিং বিভাজনের গতির জন্য একটি পরীক্ষা হবে))
সাহায্য করার জন্য সবাইকে ধন্যবাদ।
চূড়ান্ত সম্পাদনা / সমাধান:
আলফের গৃহীত উত্তর দেখুন দয়া করে। যেহেতু অজগরটি স্ট্রিংগুলির সাথে কঠোরভাবে রেফারেন্স দিয়ে কাজ করে এবং এসটিএল স্ট্রিংগুলি প্রায়শই অনুলিপি করা হয়, তাই ভ্যানিলা পাইথন বাস্তবায়নের সাথে পারফরম্যান্স আরও ভাল। তুলনার জন্য, আমি আল্ফের কোডের মাধ্যমে আমার তথ্য সংকলন করেছি এবং চালিয়েছি এবং এখানে অন্যান্য সমস্ত রানগুলির মতো একই মেশিনে পারফরম্যান্স রয়েছে, যা মূলত নিষ্পাপ অজগর বাস্তবায়নের সাথে সমান (যদিও পাইথন প্রয়োগের চেয়ে দ্রুততর যা তালিকা পুনরায় সেট / সংযোজন করে, যেমন উপরের সম্পাদনায় প্রদর্শিত):
$ /usr/bin/time cat test_lines_double | ./split6
15.09 real 0.01 user 0.45 sys
C++ : Saw 20000000 lines in 15 seconds. Crunch speed: 1333333
আমার কেবলমাত্র ছোট ছোট গ্রিপ এই ক্ষেত্রে সম্পাদন করতে সি ++ পেতে প্রয়োজনীয় পরিমাণের পরিমাণ সম্পর্কিত।
এই সমস্যাটি থেকে এবং গতকালের স্টিডিন লাইন পড়ার সমস্যাটি (উপরের লিঙ্কযুক্ত) এর মধ্যে একটি পাঠটি হ'ল ভাষার আপেক্ষিক "ডিফল্ট" পারফরম্যান্স সম্পর্কে নিষ্প্রভ অনুমানের পরিবর্তে সর্বদা একটি মানদণ্ড হওয়া উচিত। আমি শিক্ষার প্রশংসা করি।
আপনার পরামর্শের জন্য সবার আবার ধন্যবাদ!