আমি নিম্নলিখিত সেটআপটির সাথে কিছু প্রোফাইলিং করেছি: পরীক্ষার মেশিনটি (এএমডি অ্যাথলোন x৪ x2 3800+) বুট করা হয়েছিল, লং মোডে স্যুইচ করা হয়েছে (বাধা অক্ষম করা হয়েছে) এবং আগ্রহের নির্দেশটি একটি লুপে কার্যকর করা হয়েছিল, 100 পুনরাবৃত্তিগুলি অনিয়ন্ত্রিত এবং এক হাজার লুপ চক্র। লুপের বডিটি 16 বাইটে সারিবদ্ধ হয়েছিল। লুপটির আগে এবং পরে rdtsc নির্দেশনা দিয়ে সময়টি পরিমাপ করা হয়েছিল। অতিরিক্তভাবে কোনও নির্দেশ ছাড়াই একটি ডামি লুপটি কার্যকর করা হয়েছিল (যা লুপ পুনরাবৃত্তির জন্য 2 টি চক্র এবং বাকীটির জন্য 14 টি চক্র পরিমাপ করা হয়েছিল) এবং ফলাফলটি নির্দেশিকা প্রোফাইলের ফলাফল থেকে বাদ দেওয়া হয়েছিল।
নিম্নলিখিত নির্দেশাবলী পরিমাপ করা হয়েছিল:
- "
lock cmpxchg [rsp - 8], rdx
" (উভয় তুলনা ম্যাচ এবং মিল)
- "
lock xadd [rsp - 8], rdx
",
- "
lock bts qword ptr [rsp - 8], 1
"
সমস্ত ক্ষেত্রে সময়টি মাপা হয় প্রায় 310 চক্র, ত্রুটিটি প্রায় +/- 8 চক্র ছিল
এটি একই (ক্যাশেড) স্মৃতিতে পুনরাবৃত্তি কার্যকর করার মান। অতিরিক্ত ক্যাশে মিস সহ সময়গুলি যথেষ্ট বেশি। এছাড়াও এটি সক্রিয়ভাবে 2 টি কোরের একটি দিয়েই করা হয়েছিল, সুতরাং ক্যাশেটি একচেটিয়া মালিকানাধীন ছিল এবং কোনও ক্যাশে সমন্বয় প্রয়োজন হয়নি is
ক্যাশে মিসে লক করা নির্দেশের ব্যয়টি মূল্যায়নের জন্য, আমি wbinvld
লক করা নির্দেশের আগে একটি নির্দেশ যুক্ত করেছি এবং তুলনা লুপটিতে wbinvld
প্লাস একটি রেখেছি add [rsp - 8], rax
। উভয় ক্ষেত্রেই ব্যয় প্রতি নির্দেশের জুটিতে প্রায় 80,000 চক্র ছিল! লক বিটিএসের ক্ষেত্রে সময়ের পার্থক্য ছিল প্রতি নির্দেশ অনুসারে 180 টি চক্র।
মনে রাখবেন যে এটি পারস্পরিক বৈকল্পিক, তবে যেহেতু লক করা অপারেশনগুলি ক্রিয়াকলাপ ক্রিয়াকলাপ, তাই সম্ভবত বিলম্বের কোনও পার্থক্য নেই।
উপসংহার: একটি লক করা অপারেশন ভারী, তবে একটি ক্যাশে মিস অনেক বেশি ভারী হতে পারে। এছাড়াও: একটি লক করা অপারেশন ক্যাশে মিস করে না। এটি কেবল ক্যাশে সিঙ্ক্রোনাইজেশন ট্র্যাফিকের কারণ হতে পারে, যখন কোনও ক্যাশলাইন একচেটিয়াভাবে মালিকানাযুক্ত না হয়।
মেশিনটি বুট করতে, আমি রিএকটিওএস প্রকল্পের ফ্রিএলডিআর এর একটি x64 সংস্করণ ব্যবহার করেছি। এখানে asm উত্স কোডটি রয়েছে:
#define LOOP_COUNT 1000
#define UNROLLED_COUNT 100
PUBLIC ProfileDummy
ProfileDummy:
cli
// Get current TSC value into r8
rdtsc
mov r8, rdx
shl r8, 32
or r8, rax
mov rcx, LOOP_COUNT
jmp looper1
.align 16
looper1:
REPEAT UNROLLED_COUNT
// nothing, or add something to compare against
ENDR
dec rcx
jnz looper1
// Put new TSC minus old TSC into rax
rdtsc
shl rdx, 32
or rax, rdx
sub rax, r8
ret
PUBLIC ProfileFunction
ProfileFunction:
cli
rdtsc
mov r8, rdx
shl r8, 32
or r8, rax
mov rcx, LOOP_COUNT
jmp looper2
.align 16
looper2:
REPEAT UNROLLED_COUNT
// Put here the code you want to profile
// make sure it doesn't mess up non-volatiles or r8
lock bts qword ptr [rsp - 8], 1
ENDR
dec rcx
jnz looper2
rdtsc
shl rdx, 32
or rax, rdx
sub rax, r8
ret