Fortran (ออกแบบมาสำหรับการคำนวณทางวิทยาศาสตร์) มีตัวดำเนินการจ่ายไฟในตัวและเท่าที่ฉันรู้คอมไพเลอร์ Fortran โดยทั่วไปจะปรับการเพิ่มประสิทธิภาพให้เป็นจำนวนเต็มในแบบเดียวกับที่คุณอธิบาย C / C ++ pow()
น่าเสียดายที่ไม่ได้มีผู้ประกอบการพลังงานเพียงฟังก์ชั่นห้องสมุด สิ่งนี้ไม่ได้ป้องกันคอมไพเลอร์สมาร์ทจากการปฏิบัติpow
เป็นพิเศษและคำนวณมันในวิธีที่เร็วขึ้นสำหรับกรณีพิเศษ แต่ดูเหมือนว่าพวกเขาจะทำมันน้อยกว่าปกติ ...
หลายปีที่ผ่านมาฉันพยายามทำให้สะดวกยิ่งขึ้นในการคำนวณพลังงานจำนวนเต็มในวิธีที่ดีที่สุดและเกิดขึ้นกับสิ่งต่อไปนี้ มันคือ C ++ ไม่ใช่ C แม้ว่าและยังขึ้นอยู่กับคอมไพเลอร์ที่ค่อนข้างฉลาดเกี่ยวกับวิธีเพิ่มประสิทธิภาพ / อินไลน์สิ่งต่าง ๆ อย่างไรก็ตามหวังว่าคุณจะพบว่ามีประโยชน์ในทางปฏิบัติ:
template<unsigned N> struct power_impl;
template<unsigned N> struct power_impl {
template<typename T>
static T calc(const T &x) {
if (N%2 == 0)
return power_impl<N/2>::calc(x*x);
else if (N%3 == 0)
return power_impl<N/3>::calc(x*x*x);
return power_impl<N-1>::calc(x)*x;
}
};
template<> struct power_impl<0> {
template<typename T>
static T calc(const T &) { return 1; }
};
template<unsigned N, typename T>
inline T power(const T &x) {
return power_impl<N>::calc(x);
}
คำชี้แจงสำหรับคนที่อยากรู้อยากเห็น:สิ่งนี้ไม่ได้หาวิธีที่ดีที่สุดในการคำนวณพลัง แต่เนื่องจากการหาทางออกที่ดีที่สุดเป็นปัญหาที่สมบูรณ์แบบและนี่เป็นเพียงการทำเพื่อพลังขนาดเล็กเท่านั้น (เทียบกับการใช้pow
) ไม่มีเหตุผลที่จะยุ่งยาก พร้อมรายละเอียด
power<6>(a)
แล้วก็ใช้มันเป็น
สิ่งนี้ทำให้ง่ายต่อการพิมพ์พลัง (ไม่จำเป็นต้องสะกดคำ 6 a
s ด้วย parens) และช่วยให้คุณมีการเพิ่มประสิทธิภาพแบบนี้โดยไม่ต้องใช้-ffast-math
ในกรณีที่คุณมีสิ่งที่ต้องอาศัยความแม่นยำเช่นการสรุปผลรวม (ตัวอย่างที่จำเป็น .
คุณอาจลืมได้ว่านี่คือ C ++ และใช้ในโปรแกรม C (ถ้าคอมไพล์ด้วยคอมไพเลอร์ C ++)
หวังว่ามันจะมีประโยชน์
แก้ไข:
นี่คือสิ่งที่ฉันได้รับจากคอมไพเลอร์ของฉัน:
สำหรับa*a*a*a*a*a
,
movapd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
สำหรับ(a*a*a)*(a*a*a)
,
movapd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
mulsd %xmm0, %xmm0
สำหรับpower<6>(a)
,
mulsd %xmm0, %xmm0
movapd %xmm0, %xmm1
mulsd %xmm0, %xmm1
mulsd %xmm0, %xmm1