উভয় লুপগুলি অসীম, তবে আমরা দেখতে পাচ্ছি কোনটি পুনরাবৃত্তিতে আরও নির্দেশাবলী / সংস্থান গ্রহণ করে।
জিসিসি ব্যবহার করে, নিম্নলিখিত দুটি প্রোগ্রাম সংবিধানে বিভিন্ন স্তরের অপ্টিমাইজেশনের সংকলন করেছি:
int main(void) {
while(1) {}
return 0;
}
int main(void) {
while(2) {}
return 0;
}
এমনকি কোনও অপ্টিমাইজেশন ( -O0
) না পেয়েও উত্পন্ন সমাবেশটি উভয় প্রোগ্রামের জন্য অভিন্ন । সুতরাং, দুটি লুপের মধ্যে কোনও গতির পার্থক্য নেই।
রেফারেন্সের জন্য, এখানে উত্পন্ন সমাবেশ ( gcc main.c -S -masm=intel
একটি অপ্টিমাইজেশন পতাকা ব্যবহার করে ):
সহ -O0
:
.file "main.c"
.intel_syntax noprefix
.def __main; .scl 2; .type 32; .endef
.text
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
sub rsp, 32
.seh_stackalloc 32
.seh_endprologue
call __main
.L2:
jmp .L2
.seh_endproc
.ident "GCC: (tdm64-2) 4.8.1"
সহ -O1
:
.file "main.c"
.intel_syntax noprefix
.def __main; .scl 2; .type 32; .endef
.text
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
sub rsp, 40
.seh_stackalloc 40
.seh_endprologue
call __main
.L2:
jmp .L2
.seh_endproc
.ident "GCC: (tdm64-2) 4.8.1"
সহ -O2
এবং -O3
(একই আউটপুট):
.file "main.c"
.intel_syntax noprefix
.def __main; .scl 2; .type 32; .endef
.section .text.startup,"x"
.p2align 4,,15
.globl main
.def main; .scl 2; .type 32; .endef
.seh_proc main
main:
sub rsp, 40
.seh_stackalloc 40
.seh_endprologue
call __main
.L2:
jmp .L2
.seh_endproc
.ident "GCC: (tdm64-2) 4.8.1"
প্রকৃতপক্ষে, লুপের জন্য উত্পন্ন সমাবেশটি প্রতিটি স্তরের অপ্টিমাইজেশনের জন্য একরকম:
.L2:
jmp .L2
.seh_endproc
.ident "GCC: (tdm64-2) 4.8.1"
গুরুত্বপূর্ণ বিট হচ্ছে:
.L2:
jmp .L2
আমি সমাবেশ খুব ভালভাবে পড়তে পারি না, তবে এটি অবশ্যই একটি শর্তহীন লুপ। jmp
নির্দেশ নিঃশর্তভাবে প্রোগ্রাম ফিরে রিসেট .L2
এমনকি সত্য বিরুদ্ধে একটি মান তুলনা ছাড়া লেবেল, এবং যতক্ষণ প্রোগ্রাম একরকম সমাপ্ত হলে অবশ্যই অবিলম্বে তাই আবার আছে। এটি সরাসরি সি / সি ++ কোডের সাথে মিলে যায়:
L2:
goto L2;
সম্পাদনা:
আকর্ষণীয়ভাবে যথেষ্ট, এমনকি কোনও অপ্টিমাইজেশন ছাড়াই , নিম্নলিখিত লুপগুলি jmp
সমাবেশে সঠিক একই আউটপুট (নিঃশর্ত ) উত্পাদন করেছিল:
while(42) {}
while(1==1) {}
while(2==2) {}
while(4<7) {}
while(3==3 && 4==4) {}
while(8-9 < 0) {}
while(4.3 * 3e4 >= 2 << 6) {}
while(-0.1 + 02) {}
এমনকি আমার বিস্ময়েও:
#include<math.h>
while(sqrt(7)) {}
while(hypot(3,4)) {}
ব্যবহারকারীর দ্বারা সংজ্ঞায়িত ফাংশনগুলির সাথে বিষয়গুলি আরও কিছু আকর্ষণীয় হয়ে উঠবে:
int x(void) {
return 1;
}
while(x()) {}
#include<math.h>
double x(void) {
return sqrt(7);
}
while(x()) {}
এ -O0
, এই দুটি উদাহরণ প্রকৃতপক্ষে কল করে x
এবং প্রতিটি পুনরাবৃত্তির জন্য একটি তুলনা সম্পাদন করে।
প্রথম উদাহরণ (1 প্রত্যাবর্তন):
.L4:
call x
testl %eax, %eax
jne .L4
movl $0, %eax
addq $32, %rsp
popq %rbp
ret
.seh_endproc
.ident "GCC: (tdm64-2) 4.8.1"
দ্বিতীয় উদাহরণ (প্রত্যাবর্তন sqrt(7)
):
.L4:
call x
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jp .L4
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne .L4
movl $0, %eax
addq $32, %rsp
popq %rbp
ret
.seh_endproc
.ident "GCC: (tdm64-2) 4.8.1"
যাইহোক, -O1
উপরে এবং উপরে, তারা উভয়ই পূর্ববর্তী উদাহরণগুলির (একইভাবে jmp
পূর্ববর্তী লেবেলের নিঃশর্ত ফিরে) একই সমাবেশ তৈরি করে ।
টি এল; ডিআর
জিসিসির অধীনে বিভিন্ন লুপগুলি অভিন্ন সমাবেশে সংকলিত হয়। সংকলক ধ্রুবক মানগুলি মূল্যায়ন করে এবং প্রকৃত তুলনা সম্পাদনকে বিরক্ত করে না।
গল্পটির নৈতিকতা হ'ল:
- সি ++ উত্স কোড এবং সিপিইউ নির্দেশাবলীর মধ্যে অনুবাদের একটি স্তর রয়েছে এবং এই স্তরটির কার্য সম্পাদনের জন্য গুরুত্বপূর্ণ প্রভাব রয়েছে।
- সুতরাং, কেবল উত্স কোডটি দেখে কর্মক্ষমতা মূল্যায়ন করা যায় না।
- কম্পাইলার হওয়া উচিত এমন তুচ্ছ ক্ষেত্রে নিখুত স্মার্ট যথেষ্ট। প্রোগ্রামারদের বিস্তৃত ক্ষেত্রে তাদের সম্পর্কে তাদের চিন্তাভাবনা করা উচিত নয় ।