সেরা ক্ষেত্রে 8 চক্র, সবচেয়ে খারাপ ক্ষেত্রে 12 চক্র
যেহেতু এটি প্রশ্নে স্পষ্ট নয়, আমি আইভি ব্রিজের বিলম্বকে এই ভিত্তিতে স্থির করছি।
এখানে দৃষ্টিভঙ্গিটি হ'ল bsr
(বিট স্ক্যান রিভার্স) নির্দেশকে দরিদ্র-লোকের লগ 2 () হিসাবে ব্যবহার করা। ফলাফলটি জাম্প টেবিলের ইনডেক্স হিসাবে ব্যবহৃত হয় যাতে বিট 0 থেকে 42 এর জন্য এন্ট্রি থাকে। আমি ধরে নিচ্ছি যে bit৪ বিট ডেটাতে অপারেশনটি স্পষ্টভাবে প্রয়োজনীয়, তবে bsr
নির্দেশের ব্যবহার ঠিক আছে।
সর্বোত্তম ক্ষেত্রে ইনপুটগুলিতে, জম্পটযোগ্য এন্ট্রি ফলকে bsr
সরাসরি মাত্রায় মানচিত্র করতে পারে। উদাহরণস্বরূপ 32-63 পরিসীমা ইনপুটগুলির জন্য, bsr
ফলাফলটি 5 হবে, যা 1 এর মাত্রার সাথে ম্যাপ করা হয়েছে এই ক্ষেত্রে, নির্দেশের পথটি হ'ল:
Instruction Latency
bsrq 3
jmp 2
movl 1
jmp 2
total 8
সবচেয়ে খারাপ ক্ষেত্রে ইনপুটগুলিতে, bsr
ফলাফলটি সম্ভাব্য দুটি মাত্রার মানচিত্র তৈরি করবে, সুতরাং cmp
ইনপুট> 10 এন হয় কিনা তা পরীক্ষা করার জন্য ঝাঁকুনি দেওয়া এন্ট্রি আরও একটি অতিরিক্ত কাজ করে । উদাহরণস্বরূপ -12৪-১২7 সীমাতে ইনপুটগুলির জন্য, bsr
ফলাফলটি 6. হবে। সংশ্লিষ্ট জাম্পটেবল এন্ট্রি তারপরে ইনপুট> ১০০ পরীক্ষা করে এবং সেই অনুযায়ী আউটপুট প্রস্থকে সেট করে।
সবচেয়ে খারাপ ক্ষেত্রে পাথের পাশাপাশি, আমাদের ব্যবহারের জন্য bit৪ বিট অবিলম্বে মান লোড করার জন্য অতিরিক্ত মুভি নির্দেশনা রয়েছে cmp
, তাই সবচেয়ে খারাপ ক্ষেত্রে নির্দেশের পথটি হ'ল:
Instruction Latency
bsrq 3
jmp 2
movabsq 1
cmpq 1
ja 2
movl 1
jmp 2
total 12
কোডটি এখানে:
/* Input is loaded in %rdi */
bsrq %rdi, %rax
jmp *jumptable(,%rax,8)
.m0:
movl $0, %ecx
jmp .end
.m0_1:
cmpq $9, %rdi
ja .m1
movl $0, %ecx
jmp .end
.m1:
movl $1, %ecx
jmp .end
.m1_2:
cmpq $99, %rdi
ja .m2
movl $1, %ecx
jmp .end
.m2:
movl $2, %ecx
jmp .end
.m2_3:
cmpq $999, %rdi
ja .m3
movl $2, %ecx
jmp .end
.m3:
movl $3, %ecx
jmp .end
.m3_4:
cmpq $9999, %rdi
ja .m4
movl $3, %ecx
jmp .end
.m4:
movl $4, %ecx
jmp .end
.m4_5:
cmpq $99999, %rdi
ja .m5
movl $4, %ecx
jmp .end
.m5:
movl $5, %ecx
jmp .end
.m5_6:
cmpq $999999, %rdi
ja .m6
movl $5, %ecx
jmp .end
.m6:
movl $6, %ecx
jmp .end
.m6_7:
cmpq $9999999, %rdi
ja .m7
movl $6, %ecx
jmp .end
.m7:
movl $7, %ecx
jmp .end
.m7_8:
cmpq $99999999, %rdi
ja .m8
movl $7, %ecx
jmp .end
.m8:
movl $8, %ecx
jmp .end
.m8_9:
cmpq $999999999, %rdi
ja .m9
movl $8, %ecx
jmp .end
.m9:
movl $9, %ecx
jmp .end
.m9_10:
movabsq $9999999999, %rax
cmpq %rax, %rdi
ja .m10
movl $9, %ecx
jmp .end
.m10:
movl $10, %ecx
jmp .end
.m10_11:
movabsq $99999999999, %rax
cmpq %rax, %rdi
ja .m11
movl $10, %ecx
jmp .end
.m11:
movl $11, %ecx
jmp .end
.m11_12:
movabsq $999999999999, %rax
cmpq %rax, %rdi
ja .m12
movl $11, %ecx
jmp .end
.m12:
movl $12, %ecx
jmp .end
jumptable:
.quad .m0
.quad .m0
.quad .m0
.quad .m0_1
.quad .m1
.quad .m1
.quad .m1_2
.quad .m2
.quad .m2
.quad .m2_3
.quad .m3
.quad .m3
.quad .m3
.quad .m3_4
.quad .m4
.quad .m4
.quad .m4_5
.quad .m5
.quad .m5
.quad .m5_6
.quad .m6
.quad .m6
.quad .m6
.quad .m6_7
.quad .m7
.quad .m7
.quad .m7_8
.quad .m8
.quad .m8
.quad .m8_9
.quad .m9
.quad .m9
.quad .m9
.quad .m9_10
.quad .m10
.quad .m10
.quad .m10_11
.quad .m11
.quad .m11
.quad .m11_12
.quad .m12
.quad .m12
.quad .m12
.end:
/* output is given in %ecx */
এটি বেশিরভাগ জিসিসি এসেম্বলারের আউটপুট থেকে আমার লেখা সি-কোডের প্রুফ-অফ-কনসেপ্টের জন্য উত্পন্ন হয়েছিল । নোট করুন সি কোডটি জাম্প টেবিলটি প্রয়োগ করতে একটি গণনামূলক গোটো ব্যবহার করে। এটি __builtin_clzll()
জিসিসি অন্তর্নির্মিত ব্যবহার করে , যা bsr
নির্দেশনা (প্লাস এ xor
) সংকলন করে ।
আমি এটি পৌঁছানোর আগে বেশ কয়েকটি সমাধান বিবেচনা করেছি:
FYL2X
প্রাকৃতিক লগ গণনা করতে, তারপরে FMUL
প্রয়োজনীয় ধ্রুবক দ্বারা। এটি সম্ভবত [ট্যাগ: নির্দেশনা: গল্ফ] প্রতিযোগিতা হলে এটি জিততে পারে। কিন্তু FYL2X
আইভি ব্রিজ জন্য 90-106 এর লেটেন্সি যেমন হয়েছে।
হার্ড-কোডেড বাইনারি অনুসন্ধান। এটি আসলে প্রতিযোগিতামূলক হতে পারে - আমি এটি প্রয়োগ করতে অন্য কারও কাছে রেখে দেব :)।
ফলাফলগুলির সন্ধানের সম্পূর্ণ সারণী। এটি আমি নিশ্চিত যে তাত্ত্বিকভাবে দ্রুততম, তবে 1TB লুক টেবিলের প্রয়োজন হবে - এটি এখনও ব্যবহারিক নয় - সম্ভবত কয়েক বছরের মধ্যে যদি মুরের আইন ধরে রাখা থাকে।