- CPython प्रोजेक्ट ने हाल ही में bytecode इंटरप्रेटर के लिए एक नई implementation strategy अपनाई है। शुरुआती नतीजों में अलग-अलग platforms पर औसतन 10-15% प्रदर्शन सुधार दिखा।
- हालांकि, यह प्रदर्शन सुधार मुख्य रूप से LLVM 19 के regression को bypass करने का परिणाम था। बेहतर baselines (जैसे GCC, clang-18, या खास tuning flags वाले LLVM 19) से तुलना करने पर प्रदर्शन सुधार घटकर 1-5% रह गया।
प्रदर्शन परिणाम
- कई compilers और configuration options का उपयोग करके CPython इंटरप्रेटर के कई builds का benchmark किया गया। परीक्षण Intel server और Apple M1 Macbook Air पर किए गए।
- सभी builds में LTO और PGO का उपयोग किया गया।
clang18 को baseline मानते हुए pypeformance/pyperf compare_to में reported averages का उपयोग किया गया।
- Compiler performance comparison
- Apple M1 Macbook Air :
- clang18: baseline
- clang19: 1.12x धीमा
- clang19.taildup: 1.02x धीमा
- clang19.tc: 1.00x धीमा
- gcc: N/A
- tail-call इंटरप्रेटर ने फिर भी clang-18 की तुलना में speedup दिखाया, लेकिन clang-19 पर जाने के साथ slowdown कहीं अधिक नाटकीय था।
LLVM regression
संक्षिप्त पृष्ठभूमि
- पारंपरिक bytecode इंटरप्रेटर
while loop के भीतर switch statement से बना होता है। अधिकांश compilers switch को jump table में compile करते हैं।
- आधुनिक C compilers label के address लेने और उन्हें "computed goto" के रूप में उपयोग करने वाले pattern को support करते हैं। CPython ने tail-call काम से पहले तक इसी pattern का उपयोग किया था।
LLVM 19 regression
- LLVM 19 ने tail-duplication pass पर सीमाएं लगा दीं, ताकि IR size किसी निश्चित सीमा से अधिक होने पर duplication रुक जाए। इसके कारण CPython में सभी dispatch jumps merge हो गए, और computed
goto-based implementation का उद्देश्य पूरी तरह निष्फल हो गया।
अतिरिक्त असामान्यताएं
- यह तो स्पष्ट है कि tail-call duplication logic में बदलाव ने regression पैदा किया, लेकिन regression के परिमाण को पूरी तरह समझाया नहीं जा सकता।
- आधुनिक processors पर 2-4% का speedup अधिक सामान्य है।
क्या computed goto ज़रूरी है?
clang19.nocg benchmark दावा करता है कि वह clang19 से तेज़ है। यह दिखाता है कि compiler switch-based इंटरप्रेटर का उपयोग करके वही optimization कर सकता है।
सुधार
- LLVM pull request 114990 ने regression को ठीक किया। इस fix ने अपेक्षित performance को बहाल कर दिया।
विचार
benchmarking के बारे में
- सिस्टम optimization करते समय benchmarks और benchmarking methodology तैयार की जाती है, और प्रस्तावित बदलावों का मूल्यांकन किया जाता है।
- benchmarks को किसी एक data point को सामान्यीकृत करने के लिए अधिक assumptions और विश्वास की आवश्यकता होती है।
baseline
- जब कोई नया solution या method प्रस्तावित किया जाता है, तो उसकी तुलना "मौजूदा सबसे अच्छी ज्ञात approach" से करना सामान्य बात है।
software engineering के बारे में
- software systems जटिल, परस्पर जुड़े हुए और तेज़ी से बदलने वाले हैं।
- optimizing compilers पर programmer के इरादे का सम्मान करते हुए code को optimize करने का दबाव रहता है।
optimizing compilers
musttail attribute optimization से जुड़े compiler features की एक नई श्रेणी को दर्शाता है। यह performance-sensitive code लिखने के लिए अधिक शक्तिशाली शैली दे सकता है।
nix के बारे में एक और बात
nix इस प्रोजेक्ट में बहुत उपयोगी रहा। इसने Python इंटरप्रेटर के कई versions को manage और build करने में बड़ी मदद की।
1 टिप्पणियां
Hacker News टिप्पणियाँ
नमस्ते। मैं वही व्यक्ति हूँ जिसने CPython में tail-calling interpreter जोड़ने वाला PR लिखा था
benchmarking सच में बहुत कठिन काम है
लेखक ने इस समस्या की सच्चाई सामने लाई, इसके लिए प्रशंसा बनती है
यह इस बात का अच्छा उदाहरण है कि C कोई "machine के क़रीब" language नहीं है
compiler loops को जिस तरह व्यवस्थित करता है, उसके कारण tail-call interpreter उतना प्रभावी नहीं है जितना बताया गया था
Python build की performance का मूल्यांकन करना बहुत कठिन है
संबंधित चर्चा:
शानदार लेख है
हाल ही में मैंने Python 3.9 से 3.13 तक benchmarking की
सोच रहा हूँ कि इस तरह का optimization tail-call optimization से कैसे संबंधित है