ฉันตัดสินใจรันการทดสอบบนเครื่องของฉันเองโดยใช้รหัส Lik32 ฉันต้องเปลี่ยนเนื่องจาก windows หรือคอมไพเลอร์ของฉันคิดว่าความละเอียดสูงคือ 1ms ใช้
mingw32-g ++. exe -O3 -Wall -std = c ++ 11 -fexceptions -g
vector<int> rand_vec(10000000);
GCC ได้ทำการเปลี่ยนแปลงแบบเดียวกันกับรหัสต้นฉบับทั้งสอง
โปรดทราบว่ามีเพียงการทดสอบสองเงื่อนไขแรกเท่านั้นเนื่องจากเงื่อนไขที่สามต้องเป็นจริงเสมอ GCC เป็น Sherlock ที่นี่
ย้อนกลับ
.L233:
mov DWORD PTR [rsp+104], 0
mov DWORD PTR [rsp+100], 0
mov DWORD PTR [rsp+96], 0
call std::chrono::_V2::system_clock::now()
mov rbp, rax
mov rax, QWORD PTR [rsp+8]
jmp .L219
.L293:
mov edx, DWORD PTR [rsp+104]
add edx, 1
mov DWORD PTR [rsp+104], edx
.L217:
add rax, 4
cmp r14, rax
je .L292
.L219:
mov edx, DWORD PTR [rax]
cmp edx, 94
jg .L293 // >= 95
cmp edx, 19
jg .L218 // >= 20
mov edx, DWORD PTR [rsp+96]
add rax, 4
add edx, 1 // < 20 Sherlock
mov DWORD PTR [rsp+96], edx
cmp r14, rax
jne .L219
.L292:
call std::chrono::_V2::system_clock::now()
.L218: // further down
mov edx, DWORD PTR [rsp+100]
add edx, 1
mov DWORD PTR [rsp+100], edx
jmp .L217
And sorted
mov DWORD PTR [rsp+104], 0
mov DWORD PTR [rsp+100], 0
mov DWORD PTR [rsp+96], 0
call std::chrono::_V2::system_clock::now()
mov rbp, rax
mov rax, QWORD PTR [rsp+8]
jmp .L226
.L296:
mov edx, DWORD PTR [rsp+100]
add edx, 1
mov DWORD PTR [rsp+100], edx
.L224:
add rax, 4
cmp r14, rax
je .L295
.L226:
mov edx, DWORD PTR [rax]
lea ecx, [rdx-20]
cmp ecx, 74
jbe .L296
cmp edx, 19
jle .L297
mov edx, DWORD PTR [rsp+104]
add rax, 4
add edx, 1
mov DWORD PTR [rsp+104], edx
cmp r14, rax
jne .L226
.L295:
call std::chrono::_V2::system_clock::now()
.L297: // further down
mov edx, DWORD PTR [rsp+96]
add edx, 1
mov DWORD PTR [rsp+96], edx
jmp .L224
ดังนั้นนี่จึงไม่ได้บอกอะไรเรามากนักยกเว้นว่ากรณีสุดท้ายไม่จำเป็นต้องมีการทำนายสาขา
ตอนนี้ฉันลองชุดค่าผสมทั้งหมด 6 ค่าจากนั้นค่าบนสุด 2 ตัวเป็นแบบย้อนกลับและเรียงลำดับดั้งเดิม สูงคือ> = 95, ต่ำคือ <20, กลางคือ 20-94 พร้อมการทำซ้ำ 10,000,000 ครั้ง
high, low, mid: 43000000ns
mid, low, high: 46000000ns
high, mid, low: 45000000ns
low, mid, high: 44000000ns
mid, high, low: 46000000ns
low, high, mid: 44000000ns
high, low, mid: 44000000ns
mid, low, high: 47000000ns
high, mid, low: 44000000ns
low, mid, high: 45000000ns
mid, high, low: 46000000ns
low, high, mid: 45000000ns
high, low, mid: 43000000ns
mid, low, high: 47000000ns
high, mid, low: 44000000ns
low, mid, high: 45000000ns
mid, high, low: 46000000ns
low, high, mid: 44000000ns
high, low, mid: 42000000ns
mid, low, high: 46000000ns
high, mid, low: 46000000ns
low, mid, high: 45000000ns
mid, high, low: 46000000ns
low, high, mid: 43000000ns
high, low, mid: 43000000ns
mid, low, high: 47000000ns
high, mid, low: 44000000ns
low, mid, high: 44000000ns
mid, high, low: 46000000ns
low, high, mid: 44000000ns
high, low, mid: 43000000ns
mid, low, high: 48000000ns
high, mid, low: 44000000ns
low, mid, high: 44000000ns
mid, high, low: 45000000ns
low, high, mid: 45000000ns
high, low, mid: 43000000ns
mid, low, high: 47000000ns
high, mid, low: 45000000ns
low, mid, high: 45000000ns
mid, high, low: 46000000ns
low, high, mid: 44000000ns
high, low, mid: 43000000ns
mid, low, high: 47000000ns
high, mid, low: 45000000ns
low, mid, high: 45000000ns
mid, high, low: 46000000ns
low, high, mid: 44000000ns
high, low, mid: 43000000ns
mid, low, high: 46000000ns
high, mid, low: 45000000ns
low, mid, high: 45000000ns
mid, high, low: 45000000ns
low, high, mid: 44000000ns
high, low, mid: 42000000ns
mid, low, high: 46000000ns
high, mid, low: 44000000ns
low, mid, high: 45000000ns
mid, high, low: 45000000ns
low, high, mid: 44000000ns
1900020, 7498968, 601012
Process returned 0 (0x0) execution time : 2.899 s
Press any key to continue.
เหตุใดจึงมีคำสั่งซื้อสูง, ต่ำ, med จึงเร็วขึ้น (เล็กน้อย)
เพราะสิ่งที่ไม่สามารถคาดเดาได้มากที่สุดเป็นสิ่งสุดท้ายและดังนั้นจึงไม่เคยวิ่งผ่านตัวทำนายสาขา
if (i >= 95) ++nHigh; // most predictable with 94% taken
else if (i < 20) ++nLow; // (94-19)/94% taken ~80% taken
else if (i >= 20 && i < 95) ++nMid; // never taken as this is the remainder of the outfalls.
ดังนั้นกิ่งไม้จะถูกทำนายเอาไปยึดและส่วนที่เหลือด้วย
6% + (0.94 *) 20% การคาดการณ์ผิดพลาด
"เรียง"
if (i >= 20 && i < 95) ++nMid; // 75% not taken
else if (i < 20) ++nLow; // 19/25 76% not taken
else if (i >= 95) ++nHigh; //Least likely branch
กิ่งไม้จะถูกทำนายโดยที่ไม่ได้ถ่ายไม่ได้ถ่ายและ Sherlock
25% + (0.75 *) 24% การคาดการณ์ผิด
ให้ความแตกต่าง 18-23% (วัดความแตกต่างของ ~ 9%) แต่เราต้องคำนวณรอบแทนการคาดคะเน% ผิด
สมมติว่ามีการลงโทษที่ไม่ถูกต้อง 17 รอบบนซีพียู Nehalem ของฉันและการตรวจสอบแต่ละครั้งใช้เวลา 1 รอบในการออก (4-5 คำแนะนำ) และวนรอบใช้เวลาหนึ่งรอบเกินไป การพึ่งพาข้อมูลคือตัวนับและตัวแปรลูป แต่เมื่อการคาดการณ์ผิดไปจากที่ควรจะไม่ส่งผลต่อเวลา
ดังนั้นสำหรับ "ย้อนกลับ" เราจะได้เวลา (นี่ควรเป็นสูตรที่ใช้ในสถาปัตยกรรมคอมพิวเตอร์: วิธีเชิงปริมาณ IIRC)
mispredict*penalty+count+loop
0.06*17+1+1+ (=3.02)
(propability)*(first check+mispredict*penalty+count+loop)
(0.19)*(1+0.20*17+1+1)+ (= 0.19*6.4=1.22)
(propability)*(first check+second check+count+loop)
(0.75)*(1+1+1+1) (=3)
= 7.24 cycles per iteration
และเหมือนกันสำหรับ "เรียงลำดับ"
0.25*17+1+1+ (=6.25)
(1-0.75)*(1+0.24*17+1+1)+ (=.25*7.08=1.77)
(1-0.75-0.19)*(1+1+1+1) (= 0.06*4=0.24)
= 8.26
(8.26-7.24) /8.26 = 13.8% เทียบกับ ~ 9% ที่วัด (ใกล้กับที่วัด!?!)
ดังนั้นความชัดเจนของ OP จึงไม่ชัดเจน
ด้วยการทดสอบเหล่านี้การทดสอบอื่น ๆ ที่มีรหัสซับซ้อนมากขึ้นหรือการพึ่งพาข้อมูลมากขึ้นจะแตกต่างกันอย่างแน่นอนดังนั้นวัดเคสของคุณ
การเปลี่ยนลำดับของการทดสอบเปลี่ยนผลลัพธ์ แต่อาจเป็นเพราะการจัดแนวที่แตกต่างกันของการเริ่มลูปซึ่งควรจะเป็นแนว 16 ไบต์ในซีพียู Intel รุ่นใหม่ทั้งหมด แต่ไม่ได้อยู่ในกรณีนี้