X86 সমাবেশে মাত্রার ক্রম গণনা করার দ্রুততম উপায়


12

টাস্কটি সহজ: অ্যাসেমব্লিক লিখুন যা সংখ্যার যতটা সম্ভব ঘড়ির চক্র ব্যবহার করে একটি পূর্ণসংখ্যার প্রস্থের ক্রমকে গণনা করে।

  • মাত্রার ক্রম হিসাবে সংজ্ঞায়িত করা হয় log10, না log2
  • বৈধ ইনপুট পরিসীমা হয় 0থেকে , সমেত। এই সীমার বাইরে ইনপুট জন্য আচরণ অপরিজ্ঞাত।1012
  • প্রদত্ত ইনপুটটি হওয়া উচিত ব্যতীত মানগুলি নিকটতম পূর্ণসংখ্যায় গোল করা 0উচিত 0। (আপনি এটিকে স্বাক্ষরবিহীন পূর্ণসংখ্যার ক্ষেত্রে নেতিবাচক অনন্তের সেরা উপস্থাপনা হিসাবে বিবেচনা করতে পারেন)।
  • X86 সমাবেশ হতে হবে।
  • পূর্ণসংখ্যা অবশ্যই একটি রানটাইম মান হতে হবে , কোনও স্ট্যাটিক / ইনলাইন পূর্ণসংখ্যা নয়। তাই সংকলনের সময় এটি কী তা আমরা জানি না।
  • ধরে নিন যে আপনি ইতিমধ্যে একটি রেজিস্টারে একটি পূর্ণসংখ্যা লোড করেছেন। (তবে স্বচ্ছতার জন্য উত্তরে রেজিস্টারে মান নির্ধারণের অন্তর্ভুক্ত করুন)।
  • কোনও বাহ্যিক গ্রন্থাগার বা ফাংশন কল করতে পারবেন না।
  • ইন্টেল ডক্সে যে কোনও উপলভ্য নির্দেশাবলী বিনামূল্যে ব্যবহার করতে পারেন ।
  • না সি।
  • ~ 7 ইন্টেল কোর আর্কিটেকচারের কোনওটি গ্রহণযোগ্য ( 10 পৃষ্ঠায় তালিকাভুক্ত )। আদর্শভাবে নেহালেম (ইন্টেল কোর আই 7)।

বিজয়ী উত্তরটি এমন একটি যা সম্ভব সবচেয়ে কম ঘড়ির চক্র ব্যবহার করে। অর্থাৎ এটি প্রতি সেকেন্ডে সর্বাধিক অপারেশন করতে পারে। আনুমানিক ক্লক চক্রের সংক্ষিপ্তসারগুলি এখানে: http://www.agner.org/optimize/in تعمیر_tables.pdf । উত্তর পোস্ট হওয়ার পরে ঘড়ির চক্র গণনা করা যেতে পারে।


'FYL2X' এবং অন্যান্য FPU নির্দেশাবলী অনুমোদিত?
ডিজিটাল ট্রমা

1
ফলাফলটি পূর্ণসংখ্যা হওয়া উচিত? যদি তা হয় তবে কীভাবে এটি গোল করা উচিত?
ডিজিটাল ট্রমা

3
সুতরাং ইনপুট এবং আউটপুট উভয় পূর্ণসংখ্যা, হ্যাঁ? তবে ইনপুটটি 10 ​​^ 12 এর মতো দুর্দান্ত হতে পারে, তাই এটি 32 বিট ইন্টের জন্য খুব বড়। সুতরাং আমরা কি 64 বিট পূর্ণসংখ্যার ইনপুট ধরে নিই?
পল আর

3
বিজয়ী মানদণ্ডটি চক্রের সর্বাধিক বা গড় সংখ্যার উপর ভিত্তি করে? এবং যদি এটির গড় হয় তবে ইনপুট বিতরণ কী?
রানার 1212

2
কোন প্রসেসর লক্ষ্যবস্তু? লিঙ্কযুক্ত নথিতে 20 টিরও বেশি বিভিন্ন প্রক্রিয়া (এএমডি, ইন্টেল, অন্যান্য) তালিকাভুক্ত করা হয়েছে এবং বিলম্বনে যথেষ্ট পার্থক্য রয়েছে।
ডিজিটাল ট্রমা

উত্তর:


8

7 চক্র, ধ্রুবক সময়

এই এই প্রশ্নের উত্তরটির ভিত্তিতে একটি সমাধান এখানে দেওয়া হয়েছে । সংখ্যাটি ধরে রাখতে কত বিট প্রয়োজন তা গণনা করতে এটি BSR ব্যবহার করে। এটি অনেকগুলি বিট ধারণ করতে পারে এমন বৃহত্তম সংখ্যার প্রতিনিধিত্ব করতে কত দশমিক সংখ্যার প্রয়োজন তা দেখায়। তারপরে এটি যদি সংখ্যাটি 10 ​​এর নিকটতম পাওয়ারের চেয়ে কম সংখ্যায় কম হয় তবে এটি 1 টি বিয়োগ করে।

    .intel_syntax noprefix
    .globl  main
main:
    mov rdi, 1000000000000              #;your value here
    bsr rax, rdi
    movzx   eax, BYTE PTR maxdigits[1+rax]
    cmp rdi, QWORD PTR powers[0+eax*8]
    sbb al, 0
    ret
maxdigits:
    .byte   0
    .byte   0
    .byte   0
    .byte   0
    .byte   1
    .byte   1
    .byte   1
    .byte   2
    .byte   2
    .byte   2
    .byte   3
    .byte   3
    .byte   3
    .byte   3
    .byte   4
    .byte   4
    .byte   4
    .byte   5
    .byte   5
    .byte   5
    .byte   6
    .byte   6
    .byte   6
    .byte   6
    .byte   7
    .byte   7
    .byte   7
    .byte   8
    .byte   8
    .byte   8
    .byte   9
    .byte   9
    .byte   9
    .byte   9
    .byte   10
    .byte   10
    .byte   10
    .byte   11
    .byte   11
    .byte   11
    .byte   12
powers:
    .quad   0
    .quad   10
    .quad   100
    .quad   1000
    .quad   10000
    .quad   100000
    .quad   1000000
    .quad   10000000
    .quad   100000000
    .quad   1000000000
    .quad   10000000000
    .quad   100000000000
    .quad   1000000000000

উবুন্টুর জন্য জিসিসি 4.6.3 এ সংকলন করে প্রস্থান কোডটিতে মান প্রদান করে।

আমি কোনও আধুনিক প্রসেসরের জন্য সেই চক্র টেবিলটি ব্যাখ্যা করার বিষয়ে আত্মবিশ্বাসী নই, তবে @ ডিজিটালট্রামার পদ্ধতিটি ব্যবহার করে, নেহালিম প্রসেসরের উপর, আমি 7 পেয়েছি ?

ins        uOps Latency
---        -    - 
BSR r,r  : 1    3
MOVZX r,m: 1    -
CMP m,r/i: 1    1 
SBB r,r/i: 2    2

ওহ - আমি আমার লেখা শুরু করার পরে ডিজিটালট্রামার দেখেছি। অনুরূপ ধারণা। তাঁর গণনা পদ্ধতিটি ব্যবহার করে আমি মনে করি বিএসআর, এমওভি, সিএমপি, এসবিবি
অ্যাশেলি

হ্যাঁ, আমার মনে হয় তোমার আমার মার আছে। খালি দেখানোর জন্য ক) আমি কোনও এসেম্বলি প্রোগ্রামার নই এবং খ) সমাবেশটি কেবলমাত্র আমাদের দ্বারা একা ছেড়ে যায় ;-)
ডিজিটাল ট্রমা

The integer must be a runtime value, not a static/inline integer. So we don't know what it is at compile time.
বিড়াল

1
ঠিক আছে, এবং পরের লাইনটি বলে: "ধরে নিন যে আপনার একটি রেজিস্টারে ইন্টিজার ইতিমধ্যে লোড হয়েছে ((তবে স্বচ্ছতার উত্তরে রেজিস্টারে মান নির্ধারণ অন্তর্ভুক্ত করুন)"। আমি যা করেছি
অ্যাশেলি

মুভ আল এর সাথে মুভজ্যাক্স এ্যাক্স প্রতিস্থাপন করুন। ইক্সের শীর্ষ 24 বিট ইতিমধ্যে শূন্য হবে, তাই জেডএক্স নিরর্থক (এবং এটি ব্যয়বহুল)।
পিটার ফেরি

6

সেরা ক্ষেত্রে 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 লুক টেবিলের প্রয়োজন হবে - এটি এখনও ব্যবহারিক নয় - সম্ভবত কয়েক বছরের মধ্যে যদি মুরের আইন ধরে রাখা থাকে।


প্রয়োজনে আমি অনুমতিপ্রাপ্ত সমস্ত ইনপুটটির জন্য গড় বিলম্বকে গণনা করতে পারি।
ডিজিটাল ট্রমা

jmpএবং jccবিলম্বিতা নেই, কেবল থ্রুপুট খরচ। শাখা-পূর্বাভাস + অনুমানমূলক বাস্তবায়ন মানে নিয়ন্ত্রণ নির্ভরতা ডেটা নির্ভরতা শৃঙ্খলার অংশ নয়।
পিটার কর্ডস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.