পাইকারের তুলনায় কোর্টিলগুলি বাছাই করা কেন?


20

পাইথনের সাজানোর কার্যকারিতাটির গতি পরীক্ষা করতে আমি নিম্নলিখিত স্ক্রিপ্টটি লিখেছিলাম:

from sys import stdin, stdout
lines = list(stdin)
lines.sort()
stdout.writelines(lines)

আমি এর পরে sort10 মিলিয়ন লাইনযুক্ত একটি ফাইলের কোর্টিল কমান্ডের সাথে এটি তুলনা করেছি :

$ time python sort.py <numbers.txt >s1.txt
real    0m16.707s
user    0m16.288s
sys     0m0.420s

$ time sort <numbers.txt >s2.txt 
real    0m45.141s
user    2m28.304s
sys     0m0.380s

বিল্ট-ইন কমান্ডটি চারটি সিপিইউ ব্যবহার করেছিল (পাইথন কেবলমাত্র একটি ব্যবহার করেছিল) তবে এটি চালাতে প্রায় 3 গুণ সময় নিয়েছিল! কি দেয়?

আমি উবুন্টু 12.04.5 (32-বিট), পাইথন 2.7.3 এবং sort8.13 ব্যবহার করছি


@ গোল্ডিলোকস হ্যাঁ এটি হ'ল, রিয়েল টাইম ব্যবহারকারীর দিকে নজর দিন।
augurar

হু - আপনি ঠিক বলেছেন। স্পষ্টতই এটি কোরিউটিলেস 8.6 তে সমান্তরাল হয়েছিল।
স্বর্ণলোকগুলি

আপনি --buffer-sizeযে sortসমস্ত উপলব্ধ শারীরিক মেমরি ব্যবহার করে তা নির্দিষ্ট করে ব্যবহার করতে পারেন এবং দেখুন যে এটি সাহায্য করে কিনা?
ইরুভার

@ 1_CR এটি 1 জিবি বাফার দিয়ে চেষ্টা করেছে, সময় নির্ধারণে কোনও উল্লেখযোগ্য পরিবর্তন নেই। এটি এর মধ্যে প্রায় .6 গিগাবাইট ব্যবহার করেছে, সুতরাং বাফারের আকার আরও বাড়ানো সাহায্য করবে না।
augurar

উত্তর:


22

ইজকাটার মন্তব্যটির উত্তরটি প্রকাশ করেছে: লোকাল-নির্দিষ্ট তুলনা। sortকমান্ড একটি বাইট অর্ডার তুলনা করতে লোকেল পরিবেশ দ্বারা নির্দেশিত, যেহেতু পাইথন অক্ষমতা ব্যবহার করে। ইউটিএফ -8 স্ট্রিং তুলনা করা বাইট স্ট্রিংগুলির তুলনায় শক্ত hard

$ time (LC_ALL=C sort <numbers.txt >s2.txt)
real    0m5.485s
user    0m14.028s
sys     0m0.404s

কীভাবে।


এবং তারা ইউটিএফ -8 স্ট্রিংয়ের জন্য কীভাবে তুলনা করবে?
গিলস 'অসন্তুষ্ট হওয়া বন্ধ করুন'

@ গিলস locale.strxfrmসাজানোর জন্য পাইথন স্ক্রিপ্টটি সংশোধন করে স্ক্রিপ্টটি ~ 32 সেকেন্ড সময় নিয়েছিল, তারপরেও দ্রুত sortতবে অনেক কম।
augurar

3
পাইথন ২.7.৩ বাইট তুলনা করছে, তবে পাইথন ৩ ইউনিকোড শব্দের তুলনা করছে। পাইথন 3.3 এই "পরীক্ষার" জন্য পাইথন 2.7 এর থেকে প্রায় দ্বিগুণ। ইউনিকোড উপস্থাপনায় কাঁচা বাইটগুলি প্যাকিংয়ের ওভারহেড পাইথন ২..3.৩ করণীয় যে ইতিমধ্যে উল্লেখযোগ্য প্যাকিং বস্তুগুলির চেয়ে আরও বেশি।
অ্যান্থন

2
আমি একই ধীর গতিতে পেয়েছি cutএবং অন্যরাও। বিভিন্ন মেশিন আমি এখন export LC_ALL=C.bashrc। তবে সাবধান থাকুন: এটি উদাহরণস্বরূপ নামকরণের জন্য মূলত বিরতি wc(ব্যতীত wc -l)। "ব্যাড বাইটস" মোটেও গণনা করা হয় না ...
ওয়াল্টার ট্রস

1
এই কর্মক্ষমতা সমস্যা এছাড়াও ক্ষেত্রেও একই ঘটনা ঘটে grep: যদি আপনি পেতে পারেন সারগর্ভ যখন হল UTF-8 নিষ্ক্রিয়, বিশেষত যখন করে বিশাল ফাইল grepping কর্মক্ষমতা বৃদ্ধিgrep -i
আদ্রিয়ান প্রন্ক

7

এটি প্রকৃত উত্তরের চেয়ে অতিরিক্ত বিশ্লেষণের চেয়ে বেশি তবে এটি সাজানো ডেটার উপর নির্ভর করে আলাদা হয় বলে মনে হয়। প্রথম, একটি বেস পঠন:

$ printf "%s\n" {1..1000000} > numbers.txt

$ time python sort.py <numbers.txt >s1.txt
real    0m0.521s
user    0m0.216s
sys     0m0.100s

$ time sort <numbers.txt >s2.txt
real    0m3.708s
user    0m4.908s
sys     0m0.156s

ঠিক আছে, অজগরটি অনেক দ্রুত। তবে, আপনি সংখ্যাসমূহ অনুসারে sortবাছাই করতে বলে কোর্টিলগুলি দ্রুত তৈরি করতে পারেন:

$ time sort <numbers.txt >s2.txt 
real    0m3.743s
user    0m4.964s
sys     0m0.148s

$ time sort -n <numbers.txt >s2.txt 
real    0m0.733s
user    0m0.836s
sys     0m0.100s

এটি অনেক দ্রুত তবে অজগর এখনও বিস্তৃত ব্যবধানে জিতেছে। এখন, আবার চেষ্টা করুন তবে 1 এম সংখ্যার অ-বাছাই করা তালিকা সহ:

$ sort -R numbers.txt > randomized.txt

$ time sort -n <randomized.txt >s2.txt 
real    0m1.493s
user    0m1.920s
sys     0m0.116s

$ time python sort.py <randomized.txt >s1.txt
real    0m2.652s
user    0m1.988s
sys     0m0.064s

অরক্ষিত sort -nসংখ্যাযুক্ত ডেটার জন্য কোর্টিলগুলি দ্রুততর (যদিও আপনি পাইথন সাজ্টারের cmpপ্যারামিটারটিকে আরও দ্রুত তৈরি করতে সক্ষম হতে পারেন )। কোরেটিলগুলি পতাকা sortছাড়াই এখনও উল্লেখযোগ্যভাবে ধীর -n। সুতরাং, বিশুদ্ধ সংখ্যা নয়, এলোমেলো অক্ষর সম্পর্কে কী বলা যায়?

$ tr -dc 'A-Za-z0-9' </dev/urandom | head -c1000000 | 
    sed 's/./&\n/g' > random.txt

$ time sort  <random.txt >s2.txt 
real    0m2.487s
user    0m3.480s
sys     0m0.128s

$ time python sort.py  <random.txt >s2.txt 
real    0m1.314s
user    0m0.744s
sys     0m0.068s

পাইথন এখনও কোর্টিলগুলিকে প্রহার করে তবে আপনি আপনার প্রশ্নে যা দেখান তার চেয়ে অনেক ছোট ব্যবধানে। আশ্চর্যের বিষয়, খাঁটি বর্ণানুক্রমিক ডেটা দেখার সময় এটি আরও দ্রুত:

$ tr -dc 'A-Za-z' </dev/urandom | head -c1000000 |
    sed 's/./&\n/g' > letters.txt

$ time sort   <letters.txt >s2.txt 
real    0m2.561s
user    0m3.684s
sys     0m0.100s

$ time python sort.py <letters.txt >s1.txt
real    0m1.297s
user    0m0.744s
sys     0m0.064s

এটিও লক্ষণীয় যে দু'জন একই সাজানো আউটপুট উত্পাদন করে না:

$ echo -e "A\nB\na\nb\n-" | sort -n
-
a
A
b
B

$ echo -e "A\nB\na\nb\n-" | python sort.py 
-
A
B
a
b

অদ্ভুতভাবে যথেষ্ট, --buffer-sizeবিকল্পটি আমার পরীক্ষাগুলিতে খুব বেশি (বা কোনও) পার্থক্য করতে পারে বলে মনে হচ্ছে না। উপসংহার ইন, সম্ভবতঃ goldilock এর উত্তর উল্লেখিত বিভিন্ন আলগোরিদিম কারণ, পাইথন sortদ্রুত বেশিরভাগ ক্ষেত্রেই মনে করা হয় কিন্তু সংখ্যাগত গনুহ sortপাঁচমিশালী সংখ্যার তে এটি beats 1


ওপি সম্ভবত মূল কারণটি খুঁজে পেয়েছে তবে সম্পূর্ণতার জন্য, এখানে একটি চূড়ান্ত তুলনা করা হয়েছে:

$ time LC_ALL=C sort   <letters.txt >s2.txt 
real    0m0.280s
user    0m0.512s
sys     0m0.084s


$ time LC_ALL=C python sort.py   <letters.txt >s2.txt 
real    0m0.493s
user    0m0.448s
sys     0m0.044s

1 আমার তুলনায় আরও অজগর-ফুযুক্ত কেউ ক্রমিক list.sort()বাছাইয়ের পদ্ধতিটি উল্লেখ করে একই গতিটি দেখতে টুইট পরীক্ষা করার চেষ্টা করা উচিত ।


5
পাইথন বাছাইয়ের একটি অতিরিক্ত গতির সুবিধা রয়েছে, এটি আপনার শেষ নমুনার উপর ভিত্তি করে: ASCII সংখ্যাগত ক্রম। sortবড় হাতের / ছোট হাতের তুলনাগুলির জন্য কিছুটা অতিরিক্ত কাজ করছে বলে মনে হচ্ছে।
ইজকাটা

@ ইজকাটা এটাই! আমার উত্তর নীচে দেখুন।
আগস্ট 21

1
আসলে পাইথনের কাঁচা stdinইনপুট থেকে আভ্যন্তরীণ স্ট্রিং তৈরি করে বেশ কিছুটা ওভারহেড থাকে । নম্বরে সেই রূপান্তর ( lines = map(int, list(stdin))) এবং ফিরে ( stdout.writelines(map(str,lines))) করে তোলে পুরো শ্রেণীবিভাজন ধীর যান, আপ 0.234s থেকে আমার মেশিনে 0.720s বাস্তব।
অ্যান্থন

6

দুটি বাস্তবায়ন সি-তে রয়েছে, সুতরাং সেখানে একটি স্তরের প্লেয়িং ফিল্ড। কোরিউটিলস sort দৃশ্যত মার্জোর্ট অ্যালগরিদম ব্যবহার করে । Mergesort একটি নির্দিষ্ট সংখ্যক তুলনা করে যা লগারিথ্মিকভাবে ইনপুট আকারে বৃদ্ধি করে, যেমন বড় O (n লগ এন)।

পাইথনের ধরণে একটি অনন্য সংকর মার্জ / সন্নিবেশ বাছাই, টাইমসোর্ট ব্যবহার করা হয় যা ও (এন) এর সর্বোত্তম কেস দৃশ্যের সাথে বৈকল্পিক সংখ্যার তুলনা করে - সম্ভবতঃ ইতিমধ্যে সাজানো তালিকায় - তবে সাধারণত লোগারিথমিক (আপনি যৌক্তিকভাবে, আপনি বাছাইয়ের সময় সাধারণ ক্ষেত্রে লগারিদমিকের চেয়ে ভালতর হতে পারে না)।

দুটি ভিন্ন লগারিদমিক ধরণের দেওয়া, একটি নির্দিষ্ট ডেটা সেটে অন্যের তুলনায় একটির সুবিধা পেতে পারে। একটি traditionalতিহ্যবাহী একীকরণের ধরণের পরিবর্তিত হয় না, সুতরাং এটি ডেটা নির্বিশেষে একই সঞ্চালন করবে, তবে উদাহরণস্বরূপ, কুইকোর্ট (এছাড়াও লোগারিদমিক), যা পৃথক হয়, কিছু ডেটাতে আরও ভাল সম্পাদন করে তবে অন্যের চেয়ে খারাপ।

তিনটির একটি উপাদান (বা 3 এর বেশি, যেহেতু sortসমান্তরাল হয়) বেশ কিছুটা হলেও, যা আমাকে অবাক করে তোলে যে এখানে কিছু সংকট নেই, যেমন sortডিস্কে অদলবদল করা ( -Tবিকল্পটি এটি বোঝায় বলে মনে হয়)। যাইহোক, আপনার কম সিস্টেম বনাম ব্যবহারকারীর সময় বোঝায় এটি সমস্যা নয়।


উভয় বাস্তবায়ন সি তে লিখিত হয়েছে তা ভাল কথা আমি নিশ্চিত যে আমি পাইথনে কোনও বাছাই করা অ্যালগরিদম প্রয়োগ করলে এটি অনেক বেশি, ধীর হবে।
augurar

যাইহোক, ফাইলটি 0 থেকে 1 এর মধ্যে এলোমেলোভাবে উত্পন্ন ফ্লোট মানগুলি নিয়ে গঠিত, তাই শোষণের জন্য খুব বেশি কাঠামো থাকা উচিত নয়।
'11
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.