पुनरावृत्तियों की बड़ी संख्या के साथ एक खाली के लिए लूप चल रहा है, मैं कब तक इसे चलाने के लिए ले जाता है में बेतहाशा अलग नंबरों हो रही है:.NET x64 में भी-लूप प्रदर्शन विषमता: यहां तक कि संख्या-पुनरावृत्ति संबंध भी?
public static class Program
{
static void Main()
{
var sw = new Stopwatch();
sw.Start();
for (var i = 0; i < 1000000000; ++i)
{
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
}
ऊपर में मेरी मशीन पर चारों ओर 200 मि.से चलाया जाएगा, लेकिन अगर मैं इसे 1000000001 तक बढ़ाएं, फिर यह 4x लेता है! तो अगर मैं इसे 1000000002 बना देता हूं, तो यह फिर से 200ms तक नीचे है!
यह लगता है कि पुनरावृत्तियों की संख्या भी होती है। अगर मैं for (var i = 1; i < 1000000001
पर जाता हूं, (नोट 0 के बजाय 1 से शुरू होता है) तो यह 200ms है। या यदि मैं i <= 1000000001
(से कम या के बराबर नोट) तो यह 200ms है। या (var i = 0; i < 2000000000; i += 2)
भी।
यह केवल x64 पर दिखाई देता है, लेकिन सभी .NET संस्करणों (कम से कम) 4.0 तक। यह तब भी दिखाई देता है जब डिबगर के साथ रिहाई मोड में अलग हो जाता है।
अद्यतन मैं सोच रहा था कि इस वजह से कुछ चतुर बिट JIT में स्थानांतरण, लेकिन निम्न की संभावना थी कि खंडन लगता है: यदि आप तो है कि लूप के अंदर एक वस्तु बनाने के लिए, की तरह कुछ करना कि के बारे में लेता है 4x रूप में लंबे समय भी:
public static class Program
{
static void Main()
{
var sw = new Stopwatch();
sw.Start();
object o = null;
for (var i = 0; i < 1000000000; i++)
{
o = new object();
}
sw.Stop();
Console.WriteLine(o); // use o so the compiler won't optimize it out
Console.WriteLine(sw.ElapsedMilliseconds);
}
}
यह मेरा मशीन पर चारों ओर 1 सेकंड लेता है, लेकिन फिर 1000000001 करने के लिए 1 से बढ़ रही यह 4 सेकंड लेता है। यह एक अतिरिक्त 3000 एमएमएस है, इसलिए यह वास्तव में थोड़ा स्थानांतरण के कारण नहीं हो सका, क्योंकि मूल समस्या में 3000 एमएमएस अंतर के रूप में भी दिखाया गया होगा।
शायद यह लूप के दो पुनरावृत्तियों unrolls अगर सीमा भी है और उसके बाद पता चलता है कि यात्रा की पहली छमाही के परिणाम कभी उपयोग नहीं किया और इसे बाहर का अनुकूलन। – CodesInChaos