আমি লিক 32 কোডটি ব্যবহার করে নিজের মেশিনে পরীক্ষাটি পুনরায় চালু করার সিদ্ধান্ত নিয়েছি। আমার উইন্ডোজ বা কম্পাইলার ভাবনার কারণে উচ্চ রেজোলিউশনটি 1 মিমি, আমি ব্যবহার করে এটি পরিবর্তন করতে হয়েছিল
mingw32-g ++। exe -O3 -Wall -std = c ++ 11 -পরিবর্তন -জি
vector<int> rand_vec(10000000);
জিসিসি উভয় মূল কোডে একই রূপান্তর করেছে।
মনে রাখবেন যে কেবলমাত্র দুটি প্রথম শর্তটি তৃতীয় হিসাবে সর্বদা সত্য হিসাবে পরীক্ষা করা উচিত, জিসিসি এখানে এক ধরণের শার্লক।
বিপরীত
.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
সুতরাং এটি শেষের ক্ষেত্রে কোনও শাখার পূর্বাভাসের প্রয়োজন হয় না তা ছাড়া আমাদের বেশি কিছু বলে না।
এখন আমি if এর সমস্ত 6 টি সমন্বয় চেষ্টা করেছি, শীর্ষ 2 টি মূল বিপরীত এবং সাজানো হয়েছে। উচ্চ>> = 95, কম হ'ল <20, মাঝের প্রতিটি 10000000 পুনরাবৃত্তি সহ 20-94।
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.
তাহলে কেন ক্রমটি উচ্চ, নিম্ন, মধ্যবর্তী তবে দ্রুত (প্রান্তিক)
কারণ সবচেয়ে অপ্রত্যাশিত শেষ এবং তাই কোনও শাখার ভবিষ্যদ্বাণীকের মাধ্যমে কখনও চালিত হয় না।
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
শাখাগুলি নেওয়া হয়নি, নেওয়া হয়নি এবং শার্লক নিয়ে ভবিষ্যদ্বাণী করা হবে।
25% + (0.75 *) 24% ভুল ধারণা
18-23% পার্থক্য দেওয়া (~ 9% এর পরিমাপযুক্ত পার্থক্য) তবে আমাদের ভুল অনুমানের পরিবর্তে চক্র গণনা করতে হবে।
আসুন ধরে নিই যে আমার নেহালেম সিপিইউতে 17 টি চক্রের ভুল অনুমানের জরিমানা রয়েছে এবং প্রতিটি চেক ইস্যু করতে 1 চক্র লাগে (4-5 নির্দেশ) এবং লুপটিও একটি চক্র নেয়। ডেটা নির্ভরতা হ'ল কাউন্টার এবং লুপ ভেরিয়েবলগুলি, তবে একবারের ভুল প্রভাবগুলি সময়সীমার উপর প্রভাব ফেলতে না পারে out
সুতরাং "বিপরীত" জন্য, আমরা সময়গুলি পাই (এটি কম্পিউটার আর্কিটেকচারে ব্যবহৃত সূত্র হওয়া উচিত: একটি কোয়ান্টেটিভেটিভ অ্যাপ্রোচ আইআইআরসি)।
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% পরিমাপ করা (মাপার কাছাকাছি!?!)।
সুতরাং ওপি স্পষ্টভাবে স্পষ্ট নয়।
এই পরীক্ষাগুলির সাহায্যে আরও জটিল কোড বা আরও ডেটা নির্ভরতা সহ অন্যান্য পরীক্ষা অবশ্যই আলাদা হবে তাই আপনার কেসটি পরিমাপ করুন।
পরীক্ষার ক্রম পরিবর্তন করার ফলে ফলাফলগুলি পরিবর্তিত হয়েছে তবে লুপ শুরুর বিভিন্ন প্রান্তিককরণের কারণ হতে পারে যা আদর্শভাবে সমস্ত নতুন ইনটেল সিপিইউতে 16 বাইট হওয়া উচিত তবে এই ক্ষেত্রে নয়।