এই সাধারণ লুপটি বিবেচনা করুন:
float f(float x[]) {
float p = 1.0;
for (int i = 0; i < 959; i++)
p += 1;
return p;
}
যদি আপনি জিসিসি 7 (স্ন্যাপশট) বা ঝনঝন (ট্রাঙ্ক) দিয়ে -march=core-avx2 -Ofast
আপনার সাথে সংকলন করেন তবে এর সাথে খুব সামান্য কিছু পান।
.LCPI0_0:
.long 1148190720 # float 960
f: # @f
vmovss xmm0, dword ptr [rip + .LCPI0_0] # xmm0 = mem[0],zero,zero,zero
ret
অন্য কথায় এটি কেবল লুপ ছাড়াই 960 এর উত্তর নির্ধারণ করে।
তবে আপনি যদি কোডটি পরিবর্তন করেন:
float f(float x[]) {
float p = 1.0;
for (int i = 0; i < 960; i++)
p += 1;
return p;
}
উত্পাদিত সমাবেশ আসলে লুপ যোগফল সম্পাদন করে? উদাহরণ হিসাবে ঝনঝন দেয়:
.LCPI0_0:
.long 1065353216 # float 1
.LCPI0_1:
.long 1086324736 # float 6
f: # @f
vmovss xmm0, dword ptr [rip + .LCPI0_0] # xmm0 = mem[0],zero,zero,zero
vxorps ymm1, ymm1, ymm1
mov eax, 960
vbroadcastss ymm2, dword ptr [rip + .LCPI0_1]
vxorps ymm3, ymm3, ymm3
vxorps ymm4, ymm4, ymm4
.LBB0_1: # =>This Inner Loop Header: Depth=1
vaddps ymm0, ymm0, ymm2
vaddps ymm1, ymm1, ymm2
vaddps ymm3, ymm3, ymm2
vaddps ymm4, ymm4, ymm2
add eax, -192
jne .LBB0_1
vaddps ymm0, ymm1, ymm0
vaddps ymm0, ymm3, ymm0
vaddps ymm0, ymm4, ymm0
vextractf128 xmm1, ymm0, 1
vaddps ymm0, ymm0, ymm1
vpermilpd xmm1, xmm0, 1 # xmm1 = xmm0[1,0]
vaddps ymm0, ymm0, ymm1
vhaddps ymm0, ymm0, ymm0
vzeroupper
ret
এটি কেন এবং কেন এটি ঝনঝন এবং জিসিসির জন্য হুবহু এক?
আপনি যদি প্রতিস্থাপন float
করেন তবে একই লুপের সীমা double
479 g এটি আবার জিসিসি এবং ঝনঝন করার জন্য একই।
আপডেট 1
দেখা যাচ্ছে যে জিসিসি 7 (স্ন্যাপশট) এবং ক্ল্যাং (ট্রাঙ্ক) খুব আলাদা আচরণ করে। ঝাঁকুনি যতটা আমি বলতে পারি 960 এরও কম সীমাবদ্ধতার জন্য লুপগুলি অনুকূল করে izes অন্যদিকে জিসিসি সঠিক মানের সাথে সংবেদনশীল এবং এর উচ্চতর সীমা নেই। উদাহরণস্বরূপ, যখন সীমাটি 200 (পাশাপাশি অনেকগুলি অন্যান্য মান) হয় তখন এটি লুপটি অনুকূলিত করে না তবে সীমাটি 202 এবং 20002 (পাশাপাশি অন্যান্য অনেক মান) হয় তখন তা করে।