ฉันจะต่อต้านภูมิปัญญาทั่วไปที่นี่ซึ่งstd::copy
จะมีการสูญเสียประสิทธิภาพเล็กน้อยที่มองไม่เห็น ฉันเพิ่งทดสอบและพบว่าไม่เป็นความจริง: ฉันสังเกตเห็นความแตกต่างด้านประสิทธิภาพ อย่างไรก็ตามผู้ชนะคือstd::copy
อย่างไรก็ตามผู้ชนะคือ
ฉันเขียนการใช้ C ++ SHA-2 ในการทดสอบของฉันฉันแฮช 5 สายโดยใช้ SHA-2 ทั้งสี่รุ่น (224, 256, 384, 512) และฉันวนซ้ำ 300 ครั้ง ฉันวัดเวลาโดยใช้ Boost.timer ตัวนับ 300 วนนั้นเพียงพอที่จะทำให้ผลลัพธ์ของฉันคงที่อย่างสมบูรณ์ ฉันรันการทดสอบ 5 ครั้งแต่ละครั้งสลับกันระหว่างmemcpy
รุ่นกับstd::copy
รุ่น รหัสของฉันใช้ประโยชน์จากการจับข้อมูลในกลุ่มก้อนใหญ่ที่สุดเท่าที่จะเป็นไปได้ (การใช้งานอื่น ๆ จำนวนมากทำงานด้วยchar
/ char *
ในขณะที่ฉันทำงานด้วยT
/ T *
(ซึ่งT
เป็นประเภทที่ใหญ่ที่สุดในการใช้งานของผู้ใช้ที่มีพฤติกรรมล้น) ประเภทที่ใหญ่ที่สุดที่ฉันสามารถเป็นศูนย์กลางของประสิทธิภาพของอัลกอริทึมของฉันเหล่านี้คือผลลัพธ์ของฉัน:
เวลา (เป็นวินาที) เพื่อให้การทดสอบ SHA-2 เสร็จสมบูรณ์
std::copy memcpy % increase
6.11 6.29 2.86%
6.09 6.28 3.03%
6.10 6.29 3.02%
6.08 6.27 3.03%
6.08 6.27 3.03%
ความเร็วเฉลี่ยที่เพิ่มขึ้นโดยเฉลี่ยของ std :: copy over memcpy: 2.99%
คอมไพเลอร์ของฉันคือ gcc 4.6.3 ใน Fedora 16 x86_64 -Ofast -march=native -funsafe-loop-optimizations
ธงเพิ่มประสิทธิภาพของฉัน
รหัสสำหรับการใช้งาน SHA-2 ของฉัน
ฉันตัดสินใจทำการทดสอบการใช้งาน MD5 ของฉันเช่นกัน ผลลัพธ์มีความเสถียรน้อยลงมากฉันเลยตัดสินใจวิ่ง 10 ครั้ง อย่างไรก็ตามหลังจากความพยายามครั้งแรกของฉันฉันได้รับผลลัพธ์ที่แตกต่างกันอย่างมากจากการวิ่งครั้งต่อไปดังนั้นฉันคาดว่าจะมีกิจกรรม OS บางประเภทเกิดขึ้น ฉันตัดสินใจที่จะเริ่มต้นใหม่
การตั้งค่าคอมไพเลอร์และแฟล็กเดียวกัน มี MD5 เพียงเวอร์ชันเดียวเท่านั้นและเร็วกว่า SHA-2 ดังนั้นฉันจึงทดสอบ 3000 ลูปในชุดทดสอบ 5 ชุดที่คล้ายกัน
นี่คือผลลัพธ์ 10 ข้อสุดท้ายของฉัน:
เวลา (เป็นวินาที) เพื่อให้การทดสอบ MD5 เสร็จสมบูรณ์
std::copy memcpy % difference
5.52 5.56 +0.72%
5.56 5.55 -0.18%
5.57 5.53 -0.72%
5.57 5.52 -0.91%
5.56 5.57 +0.18%
5.56 5.57 +0.18%
5.56 5.53 -0.54%
5.53 5.57 +0.72%
5.59 5.57 -0.36%
5.57 5.56 -0.18%
ความเร็วเฉลี่ยลดลงโดยเฉลี่ยของ std :: copy over memcpy: 0.11%
รหัสสำหรับการนำ MD5 ไปใช้
ผลลัพธ์เหล่านี้แนะนำว่ามีการเพิ่มประสิทธิภาพบางอย่างที่ std :: copy ใช้ในการทดสอบ SHA-2 ของฉันที่std::copy
ไม่สามารถใช้ในการทดสอบ MD5 ของฉันได้ ในการทดสอบ SHA-2 อาร์เรย์ทั้งสองถูกสร้างขึ้นในฟังก์ชั่นเดียวกับที่เรียกว่าstd::copy
/memcpy
/ในการทดสอบ MD5 ของฉันหนึ่งในอาร์เรย์ถูกส่งผ่านไปยังฟังก์ชั่นเป็นพารามิเตอร์ฟังก์ชั่น
ฉันทำการทดสอบอีกเล็กน้อยเพื่อดูว่าฉันสามารถทำอะไรได้บ้างเพื่อทำให้std::copy
เร็วขึ้นอีกครั้ง คำตอบกลายเป็นเรื่องง่าย: เปิดการเพิ่มประสิทธิภาพเวลาลิงค์ นี่คือผลลัพธ์ของฉันเมื่อเปิดใช้งาน LTO (ตัวเลือก -flto เป็น gcc):
เวลา (เป็นวินาที) เพื่อให้การทดสอบ MD5 เสร็จสมบูรณ์ด้วย -flto
std::copy memcpy % difference
5.54 5.57 +0.54%
5.50 5.53 +0.54%
5.54 5.58 +0.72%
5.50 5.57 +1.26%
5.54 5.58 +0.72%
5.54 5.57 +0.54%
5.54 5.56 +0.36%
5.54 5.58 +0.72%
5.51 5.58 +1.25%
5.54 5.57 +0.54%
การเพิ่มความเร็วเฉลี่ยโดยเฉลี่ยของ std :: คัดลอกไปที่ memcpy: 0.72%
std::copy
โดยสรุปมีไม่ปรากฏเป็นโทษประสิทธิภาพสำหรับการใช้ ในความเป็นจริงดูเหมือนว่าจะมีประสิทธิภาพเพิ่มขึ้น
คำอธิบายของผลลัพธ์
เหตุใดจึงอาจstd::copy
เพิ่มประสิทธิภาพ
ครั้งแรกฉันจะไม่คาดหวังว่ามันจะช้าลงสำหรับการดำเนินการใด ๆ ตราบใดที่การเพิ่มประสิทธิภาพของการเปิดอินไลน์ คอมไพเลอร์ทั้งหมดอินไลน์อย่างจริงจัง มันอาจเป็นการปรับให้เหมาะสมที่สำคัญที่สุดเพราะช่วยให้การปรับแต่งอื่น ๆ มีประสิทธิภาพมากขึ้น std::copy
สามารถ (และฉันสงสัยว่าการใช้งานจริงทั้งหมดทำ) ตรวจพบว่าข้อโต้แย้งนั้นสามารถคัดลอกได้เล็กน้อยและหน่วยความจำนั้นเรียงตามลำดับ ซึ่งหมายความว่าในกรณีที่เลวร้ายที่สุดเมื่อmemcpy
ถูกกฎหมายstd::copy
ควรดำเนินการไม่เลว การใช้งานเล็กน้อยของstd::copy
defers ที่memcpy
ควรเป็นไปตามเกณฑ์ของคอมไพเลอร์ของคุณ "เสมอแบบอินไลน์นี้เมื่อเพิ่มประสิทธิภาพสำหรับความเร็วหรือขนาด"
อย่างไรก็ตามstd::copy
ยังเก็บข้อมูลได้มากขึ้น เมื่อคุณโทรstd::copy
ฟังก์ชั่นจะรักษาประเภทไว้เหมือนเดิม memcpy
ทำงานในvoid *
ซึ่งจะทิ้งข้อมูลที่เป็นประโยชน์เกือบทั้งหมด ตัวอย่างเช่นถ้าฉันส่งผ่านอาร์เรย์std::uint64_t
ผู้รวบรวมหรือไลบรารี implementer อาจจะสามารถใช้ประโยชน์จากการจัดตำแหน่ง 64 บิตด้วยstd::copy
แต่มันอาจเป็นเรื่องยากที่จะทำเช่นmemcpy
นั้น การใช้อัลกอริธึมหลายอย่างเช่นงานนี้โดยการทำงานครั้งแรกในส่วนที่ไม่มีการจัดแนวที่จุดเริ่มต้นของช่วงจากนั้นส่วนที่จัดชิดแล้วส่วนที่ไม่ได้จัดแนวในตอนท้าย หากมีการรับประกันว่าจะจัดแนวทั้งหมดรหัสนั้นจะง่ายขึ้นและเร็วขึ้นและง่ายขึ้นสำหรับตัวพยากรณ์สาขาในโปรเซสเซอร์ของคุณเพื่อให้ถูกต้อง
การเพิ่มประสิทธิภาพก่อนวัย?
std::copy
อยู่ในตำแหน่งที่น่าสนใจ ฉันคาดหวังว่ามันจะไม่ช้ากว่าmemcpy
และบางครั้งก็เร็วขึ้นด้วยคอมไพเลอร์การเพิ่มประสิทธิภาพที่ทันสมัย นอกจากนี้สิ่งที่คุณสามารถคุณสามารถmemcpy
ไม่อนุญาตให้มีการทับซ้อนกันในบัฟเฟอร์ในขณะที่รองรับการทับซ้อนในทิศทางเดียว ( สำหรับทิศทางอื่นของการทับซ้อน) ทำงานเฉพาะในตัวชี้ทำงานบน iterators ใด ๆ ( , , หรือประเภทที่กำหนดเองของตัวเอง) กล่าวอีกนัยหนึ่งคุณควรใช้เมื่อคุณต้องการคัดลอกข้อมูลจำนวนหนึ่งstd::copy
memcpy
std::copy
std::copy_backward
memcpy
std::copy
std::map
std::vector
std::deque
std::copy
char
สามารถลงนามหรือไม่ได้ลงนามขึ้นอยู่กับการใช้งาน หากจำนวนไบต์สามารถเป็น> = 128 ให้ใช้unsigned char
สำหรับอาร์เรย์ไบต์ของคุณ (ผู้(int *)
แสดงจะปลอดภัยเหมือน(unsigned int *)
กัน)