পটভূমি:
এম্বেড থাকা অ্যাসেম্বলি ভাষার সাথে কিছু পাস্কাল কোড অনুকূলিত করার সময় , আমি একটি অপ্রয়োজনীয় MOV
নির্দেশ লক্ষ্য করে এটিকে সরিয়ে দিয়েছি ।
আমার অবাক করে দিয়েছি, অপ্রয়োজনীয় নির্দেশনা সরিয়ে দেওয়ার কারণে আমার প্রোগ্রামটি ধীর হয়ে গেছে ।
আমি দেখতে পেয়েছি যে স্বেচ্ছাসেবী, অকেজো MOV
নির্দেশাবলী যোগ করার পরে আরও কার্যকারিতা বৃদ্ধি পেয়েছিল ।
প্রভাব লক্ষ্যভ্রষ্ট হয়, এবং মৃত্যুদন্ড অর্ডার উপর ভিত্তি করে পরিবর্তন: একই আবর্জনা নির্দেশাবলী পক্ষান্তরিত একটি একক লাইন নিচে আপ বা একটি মন্দার উত্পাদন ।
আমি বুঝতে পারি যে সিপিইউ সব ধরণের অপ্টিমাইজেশান এবং স্ট্রিমলাইনিং করে, তবে, এটি কালো যাদু বলে মনে হয়।
তথ্যটি:
আমার কোডের একটি সংস্করণ শর্তসাপেক্ষে লুপের মাঝখানে তিনটি জাঙ্ক অপারেশন সংকলন করে যা 2**20==1048576
বার বার চলে runs (পার্শ্ববর্তী প্রোগ্রামটি কেবল SHA-256 হ্যাশ গণনা করে )।
আমার বরং পুরানো মেশিনের ফলাফল (ইন্টেল (আর) কোর (টিএম) 2 সিপিইউ 6400 @ 2.13 গিগাহার্টজ):
avg time (ms) with -dJUNKOPS: 1822.84 ms
avg time (ms) without: 1836.44 ms
প্রোগ্রামগুলি একটি লুপে 25 বার সঞ্চালিত হয়, প্রতিটি সময় রান ক্রম এলোমেলোভাবে পরিবর্তিত হয়।
উদ্ধৃতাংশ:
{$asmmode intel}
procedure example_junkop_in_sha256;
var s1, t2 : uint32;
begin
// Here are parts of the SHA-256 algorithm, in Pascal:
// s0 {r10d} := ror(a, 2) xor ror(a, 13) xor ror(a, 22)
// s1 {r11d} := ror(e, 6) xor ror(e, 11) xor ror(e, 25)
// Here is how I translated them (side by side to show symmetry):
asm
MOV r8d, a ; MOV r9d, e
ROR r8d, 2 ; ROR r9d, 6
MOV r10d, r8d ; MOV r11d, r9d
ROR r8d, 11 {13 total} ; ROR r9d, 5 {11 total}
XOR r10d, r8d ; XOR r11d, r9d
ROR r8d, 9 {22 total} ; ROR r9d, 14 {25 total}
XOR r10d, r8d ; XOR r11d, r9d
// Here is the extraneous operation that I removed, causing a speedup
// s1 is the uint32 variable declared at the start of the Pascal code.
//
// I had cleaned up the code, so I no longer needed this variable, and
// could just leave the value sitting in the r11d register until I needed
// it again later.
//
// Since copying to RAM seemed like a waste, I removed the instruction,
// only to discover that the code ran slower without it.
{$IFDEF JUNKOPS}
MOV s1, r11d
{$ENDIF}
// The next part of the code just moves on to another part of SHA-256,
// maj { r12d } := (a and b) xor (a and c) xor (b and c)
mov r8d, a
mov r9d, b
mov r13d, r9d // Set aside a copy of b
and r9d, r8d
mov r12d, c
and r8d, r12d { a and c }
xor r9d, r8d
and r12d, r13d { c and b }
xor r12d, r9d
// Copying the calculated value to the same s1 variable is another speedup.
// As far as I can tell, it doesn't actually matter what register is copied,
// but moving this line up or down makes a huge difference.
{$IFDEF JUNKOPS}
MOV s1, r9d // after mov r12d, c
{$ENDIF}
// And here is where the two calculated values above are actually used:
// T2 {r12d} := S0 {r10d} + Maj {r12d};
ADD r12d, r10d
MOV T2, r12d
end
end;
এটি নিজে চেষ্টা করো:
আপনি যদি নিজে চেষ্টা করে দেখতে চান তবে কোডটি গিটহাবে অনলাইনে রয়েছে ।
আমার প্রশ্নগুলো:
- র্যামে নিবন্ধের সামগ্রী অনুলিপি করে অনর্থকভাবে কেন কার্যকারিতা বাড়িয়ে দেবে?
- কেন একই অকেজো নির্দেশাবলী কিছু লাইনে একটি গতিবেগ এবং অন্যদের উপর মন্দা সরবরাহ করবে?
- এই আচরণটি কি এমন কোনও বিষয় যা সংকলক দ্বারা পূর্বাভাসে শোষণ করা যেতে পারে?