পারফরম্যান্সের সর্বাধিক গুরুত্ব রয়েছে এমন পরিস্থিতিতে, সি সংকলক সম্ভবত আপনার হাতের সুরক্ষিত সমাবেশ ভাষা নিয়ে যা করতে পারেন তার তুলনায় দ্রুততম কোড তৈরি করবে না। আমি ন্যূনতম প্রতিরোধের পথ অবলম্বন করি - এর মতো ছোট রুটিনের জন্য, আমি কেবল এসএম কোডটি লিখি এবং এটি সম্পর্কে ভাল ধারণা রয়েছে যে এটি কার্যকর করতে কতগুলি চক্র গ্রহণ করবে। আপনি সি কোডের সাথে গলগল করতে সক্ষম হবেন এবং সংকলকটি ভাল আউটপুট তৈরি করতে পারবেন তবে আউটপুটটি সেভাবে টিউন করার জন্য আপনি প্রচুর সময় নষ্ট করতে পারেন। সংস্থাগুলি (বিশেষত মাইক্রোসফ্ট থেকে) গত কয়েক বছরে অনেক দূর এগিয়েছে, তবে তারা এখনও আপনার কানের মধ্যে সংকলকটির মতো স্মার্ট নয় কারণ আপনি নিজের নির্দিষ্ট পরিস্থিতি নিয়ে কাজ করছেন এবং কেবল একটি সাধারণ ক্ষেত্রে নয়। সংকলক নির্দিষ্ট নির্দেশাবলীর (যেমন এলডিএম) ব্যবহার করতে পারে না যা এটির গতি বাড়িয়ে তুলতে পারে এবং এটি ' লুপটি আনরোল করার জন্য যথেষ্ট স্মার্ট হওয়ার সম্ভাবনা নেই। এটি করার একটি উপায় এখানে আমার মন্তব্যে উল্লিখিত 3 টি ধারণাকে অন্তর্ভুক্ত করা হয়েছে: লুপ আনরোলিং, ক্যাশে প্রিফেচ এবং একাধিক লোড (এলডিএম) নির্দেশনা ব্যবহার করা। নির্দেশ চক্রের গণনাটি অ্যারের উপাদান অনুসারে প্রায় 3 টি ঘড়ি আসে তবে এটি মেমরির বিলম্বকে বিবেচনায় নেয় না।
পরিচালনার তত্ত্ব: এআরএমের সিপিইউ ডিজাইনটি এক ঘড়ির চক্রের বেশিরভাগ নির্দেশনা কার্যকর করে, তবে নির্দেশগুলি পাইপলাইনে কার্যকর করা হয়। সি সংকলকগুলি এর মধ্যে অন্যান্য নির্দেশাবলী আন্তঃবিভক্ত করে পাইপলাইন বিলম্বগুলি দূর করার চেষ্টা করবে। আসল সি কোডের মতো টাইট লুপের সাথে উপস্থাপন করার সময়, সংকলকটির বিলম্বগুলি লুকিয়ে রাখতে বেশ সময় লাগবে কারণ মেমরি থেকে পড়া মানটি সঙ্গে সঙ্গে তুলনা করতে হবে। আমার কোড নীচে মেমরির বিলম্ব এবং ডেটা আনার পাইপলাইনকে উল্লেখযোগ্যভাবে হ্রাস করার জন্য 4 টি নিবন্ধের 2 সেট এর মধ্যে বিকল্প হয়। সাধারণভাবে, যখন বড় ডেটা সেটগুলির সাথে কাজ করা হয় এবং আপনার কোড সর্বাধিক বা সমস্ত উপলব্ধ রেজিস্টার ব্যবহার করে না, তখন আপনি সর্বাধিক পারফরম্যান্স পাচ্ছেন না।
; r0 = count, r1 = source ptr, r2 = comparison value
stmfd sp!,{r4-r11} ; save non-volatile registers
mov r3,r0,LSR #3 ; loop count = total count / 8
pld [r1,#128]
ldmia r1!,{r4-r7} ; pre load first set
loop_top:
pld [r1,#128]
ldmia r1!,{r8-r11} ; pre load second set
cmp r4,r2 ; search for match
cmpne r5,r2 ; use conditional execution to avoid extra branch instructions
cmpne r6,r2
cmpne r7,r2
beq found_it
ldmia r1!,{r4-r7} ; use 2 sets of registers to hide load delays
cmp r8,r2
cmpne r9,r2
cmpne r10,r2
cmpne r11,r2
beq found_it
subs r3,r3,#1 ; decrement loop count
bne loop_top
mov r0,#0 ; return value = false (not found)
ldmia sp!,{r4-r11} ; restore non-volatile registers
bx lr ; return
found_it:
mov r0,#1 ; return true
ldmia sp!,{r4-r11}
bx lr
আপডেট:
মন্তব্যগুলিতে প্রচুর সংশয়ী আছেন যারা মনে করেন যে আমার অভিজ্ঞতাটি বিবৃত / মূল্যহীন এবং প্রমাণ প্রয়োজন require অপ্টিমাইজেশন -O2 ( লুপ আন্রোলিং সহ সমস্ত অপ্টিমাইজেশন চালু হয়েছে) দিয়ে নিম্নলিখিত আউটপুট তৈরি করতে আমি জিসিসি 4.8 (অ্যান্ড্রয়েড এনডিকে 9 সি থেকে ) ব্যবহার করেছি। আমি উপরের প্রশ্নে উপস্থাপিত মূল সি কোডটি সংকলিত করেছি। জিসিসি যা তৈরি করেছিল তা এখানে:
.L9: cmp r3, r0
beq .L8
.L3: ldr r2, [r3, #4]!
cmp r2, r1
bne .L9
mov r0, #1
.L2: add sp, sp, #1024
bx lr
.L8: mov r0, #0
b .L2
জিসিসির আউটপুট কেবল লুপটি আনারোল করে না, তবে এলডিআরের পরে স্টলে একটি ঘড়িও অপচয় করে। এটিতে অ্যারে উপাদানগুলির জন্য কমপক্ষে 8 টি ঘড়ি প্রয়োজন। লুপটি কখন প্রস্থান করতে হবে তা জানার জন্য এটি ঠিকানাটি ব্যবহার করার একটি ভাল কাজ করে তবে জাদুকরী জিনিসগুলির সমস্ত সংকলকরা এই কোডটিতে খুঁজে পাওয়া যায় না। আমি লক্ষ্য প্ল্যাটফর্মে কোডটি চালাচ্ছি না (আমার নিজস্ব নেই) তবে এআরএম কোড পারফরম্যান্সে যে কেউ অভিজ্ঞ সে দেখতে পাবে যে আমার কোডটি দ্রুত is
আপডেট 2:
আমি মাইক্রোসফ্টের ভিজ্যুয়াল স্টুডিও 2013 এসপি 2- কে কোড দিয়ে আরও ভাল করার সুযোগ দিয়েছি। এটি আমার অ্যারে প্রারম্ভিকরণটিকে ভেক্টরাইজ করার জন্য নিওন নির্দেশাবলী ব্যবহার করতে সক্ষম হয়েছিল, তবে ওপি দ্বারা লিখিত রৈখিক মান অনুসন্ধান জিসিসি যা তৈরি করেছিল তার সাথে মিল খুঁজে পেয়েছিল (আমি এটিকে আরও পঠনযোগ্য করার জন্য লেবেলের নামকরণ করেছি):
loop_top:
ldr r3,[r1],#4
cmp r3,r2
beq true_exit
subs r0,r0,#1
bne loop_top
false_exit: xxx
bx lr
true_exit: xxx
bx lr
যেমনটি আমি বলেছি, আমি ওপি-র সঠিক হার্ডওয়্যারটির মালিক নই, তবে আমি একটি এনভিডিয়া টেগ্রা 3 এবং টেগড়া 4 3 টি বিভিন্ন সংস্করণে পারফরম্যান্সটি পরীক্ষা করব এবং শীঘ্রই ফলাফলগুলি এখানে পোস্ট করব।
আপডেট 3:
আমি আমার কোড এবং মাইক্রোসফ্টের সংকলিত এআরএম কোডটি একটি টেগ্রা 3 এবং টেগ্রা 4 (সারফেস আরটি, সারফেস আরটি 2) তে চালিত করেছি। আমি একটি লুপের 1000000 পুনরাবৃত্তি চালিয়েছি যা কোনও মিল খুঁজে পেতে ব্যর্থ হয় যাতে সবকিছু ক্যাশে থাকে এবং এটি পরিমাপ করা সহজ।
My Code MS Code
Surface RT 297ns 562ns
Surface RT 2 172ns 296ns
উভয় ক্ষেত্রেই আমার কোডটি প্রায় দ্বিগুণ দ্রুত চলে। বেশিরভাগ আধুনিক এআরএম সিপিইউ সম্ভবত একই জাতীয় ফলাফল দেবে।