ওয়েল, আপনি যেভাবে সময় নির্ধারণ করছেন তা আমার কাছে বেশ খারাপ লাগছে। পুরো লুপটি সময় দেওয়ার জন্য এটি আরও বেশি বুদ্ধিমান হবে:
var stopwatch = Stopwatch.StartNew();
for (int i = 1; i < 100000000; i++)
{
Fibo(100);
}
stopwatch.Stop();
Console.WriteLine("Elapsed time: {0}", stopwatch.Elapsed);
এইভাবে আপনি ক্ষুদ্র সময়, ভাসমান পয়েন্ট গণিত এবং জমে থাকা ত্রুটির দয়ায় নেই।
এই পরিবর্তনটি করে, দেখুন "নন-ক্যাচ" সংস্করণটি "ক্যাচ" সংস্করণটির থেকে এখনও ধীর whether
সম্পাদনা: ঠিক আছে, আমি নিজে চেষ্টা করেছি - এবং আমি একই ফলাফল দেখছি। খুব অদ্ভুত. চেষ্টা / ক্যাচটি কিছু খারাপ ইনলাইনিং অক্ষম করছে কিনা তা নিয়ে আমি অবাক হয়েছি, তবে এর [MethodImpl(MethodImplOptions.NoInlining)]
পরিবর্তে ব্যবহার করা কোনও উপকারে আসেনি ...
মূলত আপনাকে কর্ডবিজির আওতায় অনুকূলিত জেআইটিড কোডটি দেখতে হবে, আমি সন্দেহ করি ...
সম্পাদনা: আরও কয়েকটি বিটের তথ্য:
- কেবল
n++;
লাইনের চারপাশে চেষ্টা / ধরার ফলে কর্মক্ষমতা উন্নত হয় তবে পুরো ব্লকের চারপাশে রাখার মতো নয়
- আপনি যদি একটি নির্দিষ্ট ব্যতিক্রম (
ArgumentException
আমার পরীক্ষাগুলিতে) ধরে থাকেন তবে এটি এখনও দ্রুত
- আপনি যদি ক্যাচ ব্লকে ব্যতিক্রমটি মুদ্রণ করেন তবে এটি এখনও দ্রুত
- আপনি যদি ক্যাচ ব্লকে ব্যতিক্রমটি পুনর্বিবেচনা করেন তবে এটি আবার ধীর
- আপনি যদি ক্যাচ ব্লকের পরিবর্তে শেষ অবধি ব্যবহার করেন তবে এটি আবার ধীর slow
- আপনি যদি শেষ অবধি পাশাপাশি একটি ক্যাচ ব্লক ব্যবহার করেন তবে এটি দ্রুত
অদ্ভুত ...
সম্পাদনা: ঠিক আছে, আমাদের বিচ্ছিন্ন করা হয়েছে ...
এটি সি # 2 সংকলক এবং। নেট 2 (32-বিট) সিএলআর ব্যবহার করছে, এমডিবিজি (যেমন আমার মেশিনে কর্ডবিজি নেই) দিয়ে বিচ্ছিন্ন। আমি এখনও একই সম্পাদনা প্রভাবগুলি দেখতে পাচ্ছি, এমনকি ডিবাগারের অধীনে। দ্রুত সংস্করণটি try
কেবলমাত্র একটি catch{}
হ্যান্ডলার সহ পরিবর্তনশীল ঘোষণা এবং রিটার্ন স্টেটমেন্টের মধ্যকার সবকিছুতে একটি ব্লক ব্যবহার করে । স্পষ্টতই ধীর সংস্করণটি চেষ্টা / ধরা ছাড়া বাদে একইরকম। উভয় ক্ষেত্রেই কলিং কোড (অর্থাত্ প্রধান) একই, এবং একই সমাবেশের প্রতিনিধিত্ব রয়েছে (সুতরাং এটি কোনও অন্তর্নিহিত সমস্যা নয়)।
দ্রুত সংস্করণের জন্য সংস্থানবিহীন কোড:
[0000] push ebp
[0001] mov ebp,esp
[0003] push edi
[0004] push esi
[0005] push ebx
[0006] sub esp,1Ch
[0009] xor eax,eax
[000b] mov dword ptr [ebp-20h],eax
[000e] mov dword ptr [ebp-1Ch],eax
[0011] mov dword ptr [ebp-18h],eax
[0014] mov dword ptr [ebp-14h],eax
[0017] xor eax,eax
[0019] mov dword ptr [ebp-18h],eax
*[001c] mov esi,1
[0021] xor edi,edi
[0023] mov dword ptr [ebp-28h],1
[002a] mov dword ptr [ebp-24h],0
[0031] inc ecx
[0032] mov ebx,2
[0037] cmp ecx,2
[003a] jle 00000024
[003c] mov eax,esi
[003e] mov edx,edi
[0040] mov esi,dword ptr [ebp-28h]
[0043] mov edi,dword ptr [ebp-24h]
[0046] add eax,dword ptr [ebp-28h]
[0049] adc edx,dword ptr [ebp-24h]
[004c] mov dword ptr [ebp-28h],eax
[004f] mov dword ptr [ebp-24h],edx
[0052] inc ebx
[0053] cmp ebx,ecx
[0055] jl FFFFFFE7
[0057] jmp 00000007
[0059] call 64571ACB
[005e] mov eax,dword ptr [ebp-28h]
[0061] mov edx,dword ptr [ebp-24h]
[0064] lea esp,[ebp-0Ch]
[0067] pop ebx
[0068] pop esi
[0069] pop edi
[006a] pop ebp
[006b] ret
ধীর সংস্করণের জন্য সংস্থানবিহীন কোড:
[0000] push ebp
[0001] mov ebp,esp
[0003] push esi
[0004] sub esp,18h
*[0007] mov dword ptr [ebp-14h],1
[000e] mov dword ptr [ebp-10h],0
[0015] mov dword ptr [ebp-1Ch],1
[001c] mov dword ptr [ebp-18h],0
[0023] inc ecx
[0024] mov esi,2
[0029] cmp ecx,2
[002c] jle 00000031
[002e] mov eax,dword ptr [ebp-14h]
[0031] mov edx,dword ptr [ebp-10h]
[0034] mov dword ptr [ebp-0Ch],eax
[0037] mov dword ptr [ebp-8],edx
[003a] mov eax,dword ptr [ebp-1Ch]
[003d] mov edx,dword ptr [ebp-18h]
[0040] mov dword ptr [ebp-14h],eax
[0043] mov dword ptr [ebp-10h],edx
[0046] mov eax,dword ptr [ebp-0Ch]
[0049] mov edx,dword ptr [ebp-8]
[004c] add eax,dword ptr [ebp-1Ch]
[004f] adc edx,dword ptr [ebp-18h]
[0052] mov dword ptr [ebp-1Ch],eax
[0055] mov dword ptr [ebp-18h],edx
[0058] inc esi
[0059] cmp esi,ecx
[005b] jl FFFFFFD3
[005d] mov eax,dword ptr [ebp-1Ch]
[0060] mov edx,dword ptr [ebp-18h]
[0063] lea esp,[ebp-4]
[0066] pop esi
[0067] pop ebp
[0068] ret
প্রতিটি ক্ষেত্রেই *
ডিবাগারটি একটি সাধারণ "স্টেপ-ইন" এ প্রবেশ করে।
সম্পাদনা: ঠিক আছে, আমি এখন কোডটি দেখেছি এবং আমি মনে করি প্রতিটি সংস্করণ কীভাবে কাজ করে তা আমি দেখতে পাচ্ছি ... এবং আমি বিশ্বাস করি যে ধীর সংস্করণটি ধীরতর কারণ এটিতে কম রেজিস্টার এবং আরও স্ট্যাক স্পেস ব্যবহার করা হয়েছে। এর ছোট মানগুলির জন্য n
সম্ভবত দ্রুততর - তবে যখন লুপটি বেশিরভাগ সময় নেয়, এটি ধীর হয়।
সম্ভবত চেষ্টা / ধরা ব্লক বাহিনী আরো রেজিস্টার সংরক্ষিত করা এবং পুনরুদ্ধার, তাই জে আই টি JIT লুপ জন্য ঐ পাশাপাশি ব্যবহার ... যা সামগ্রিক পারফরম্যান্সের উন্নতি ঘটবে। "সাধারণ" কোডে যত বেশি রেজিস্টার ব্যবহার না করা জেআইটির পক্ষে যুক্তিসঙ্গত সিদ্ধান্ত ছিল কিনা তা পরিষ্কার নয় ।
সম্পাদনা: আমার x64 মেশিনে এটি চেষ্টা করে দেখুন tried এই কোডের x86 সিএলআরের তুলনায় x64 সিএলআর অনেক দ্রুত (প্রায় 3-4 গুণ দ্রুত) এবং x64 এর অধীনে চেষ্টা / ক্যাচ ব্লকটি লক্ষণীয় পার্থক্য করে না।