अनुकूलित करना मैं गणित कोड लिख रहा हूं जिसे बड़ी संख्या में तेजी से गुणा करने की आवश्यकता है। यह एक पूर्णांक के साथ पूर्णांक की सरणी के गुणों को तोड़ देता है। C++ में यह इस तरह दिखता है (अहस्ताक्षरित के पर):x64 असेंबलर एमयूएल लूप
void muladd(unsigned* r, const unsigned* a, unsigned len, unsigned b) {
unsigned __int64 of = 0; // overflow
unsigned i = 0; // loop variable
while (i < len) {
of += (unsigned __int64)a[i] * b + r[i];
r[i] = (unsigned)of;
of >>= 32;
++i;
}
r[i] = (unsigned)of; // save overflow
}
मैं मैन्युअल रूप से इस पाश unrolled, यह 64 बिट में बदला जाएगा और .asm संकलक उत्पादन पर काम किया यह आगे अनुकूलन करने के लिए। मुख्य .asm पाश अब इस तरह दिखता है:
mov rax, rdi ; rdi = b
mul QWORD PTR [rbx+r10*8-64] ; rdx:rax = a[i] * b; r10 = i
mov rsi, QWORD PTR [r14+r10*8-64] ; r14 = r; rsi = r[i]
add rax, rsi
adc rdx, 0
add rax, r11 ; r11 = of (low part)
adc rdx, 0
mov QWORD PTR [r14+r10*8-64], rax ; save result
mov r11, rdx
; this repeats itself 8 times with different offsets
जब मैं बेंचमार्क इस, मुझे लगता है कि यह मेरे Core2 Quad पर गुणा प्रति avarage पर 6.3 के बारे में चक्र लेता है।
मेरा प्रश्न है: मैं इस में तेजी लाने के कर सकते हैं किसी भी तरह? दुर्भाग्यवश, मुझे जोड़ों में से किसी एक से बचने के लिए कोई रास्ता नहीं दिखता है और गुणा को हमेशा आरडीएक्स की आवश्यकता होती है: आरएक्स, इसलिए मुझे डेटा को चारों ओर स्थानांतरित करने की आवश्यकता है और "समानांतर में गुणा" की तरह नहीं हो सकता है।
कोई भी विचार किसी को भी?
अद्यतन: कुछ और परीक्षण के बाद, मैं प्रति 64-बिट एमयूएल 5.4 के बारे में चक्र की गति अप (है कि, सभी जोड़ने शामिल कदम और पाश भूमि के ऊपर) लाने के लिए प्रबंधित किया है। मुझे लगता है कि कोर 2 पर आपको सबसे अच्छा मिल सकता है, क्योंकि कोर 2 में बहुत तेज़ एमयूएल निर्देश नहीं है: इसमें 3 का थ्रूपुट और 6 (रेस 7) चक्र की विलम्ब है। सैंडी पुल 1 के थ्रूपुट और 3 (श्वास 4) चक्रों की विलम्ब के साथ बेहतर होगा।
जीएमपी के लिए बहुत कम संख्या के बारे में: मुझे मिल गया है कि उनके स्रोत कोड से और मुझे लगता है कि यह एक सैद्धांतिक संख्या है। लेकिन यह सुनिश्चित है कि यह एक संख्या है जिसे एएमडी के 9 सीपीयू के लिए गणना की गई थी। और जो मैंने पढ़ा है, उससे मैं एएमडी को (पुराने) इंटेल चिप्स की तुलना में तेज़ एमयूएल इकाई इकट्ठा करता हूं। अपनी दिनचर्या SSE से फायदा हो सकता है की तरह
आप जीएमपी में विधानसभा दिनचर्या में से कुछ पर एक नज़र लेने के लिए चाहते हो सकता है। उनके पास ऐसा फ़ंक्शन है जो वास्तव में करता है और अधिकांश प्रोसेसर के लिए x64 सहित असेंबली में लिखा जाता है। – Mysticial
जीएमपी वास्तव में एक तेजी से mul_basecase के लिए अच्छा समर्थन है और जाहिर है कि यह उन्हें प्रति एमयूएल के बारे में 2.35 चक्र लेता है, बहुत अच्छा है। अगर मैं इसे सही ढंग से समझता हूं, तो वे दो वैक्टरों को अंतःस्थापित करते हैं, जो निर्भरता को कम रखते हैं और अतिप्रवाह हैंडलिंग में सुधार करते हैं। – cxxl