2012-05-10 14 views
9

मैं एक्सएनए फ्रेमवर्क का उपयोग कर एक गेम बना रहा हूं, इसलिए मैं वैक्टर पर काम करने वाले बहुत से कार्यों का उपयोग करता हूं। (विशेष रूप से Vector2 (64 बिट संरचना))। मुझे परेशान करता है कि अधिकांश विधियों को रेफरी और आउट पैरामीटर के साथ परिभाषित किया जाता है। यहां एक उदाहरण दिया गया है:वापसी/बनाम बनाम वापसी का लाभ क्या है?

void Min(ref Vector2 value1, ref Vector2 value2, out Vector2 result) 

जो मुझे थोड़ा अजीब लग रहा है। वहाँ भी एक और Min जो और अधिक स्पष्ट

public static Vector2 Min(Vector2 value1, Vector2 value2); 

असल में, लगभग सभी कार्यों ref और out रों साथ भार के लिए है है। इसी प्रकार, अन्य APIs

इस डिज़ाइन का लाभ क्या है? एक्सएनए प्रदर्शन के लिए अनुकूलित है, क्या यह परिणाम हो सकता है? कहें, Quaternion 128b की आवश्यकता है जहां कम से कम गुजर रहा है।

संपादित करें:,

  • refOut1 2200
  • refOut2 1400

7 विन 64 बिट:

public class Game1 : Microsoft.Xna.Framework.Game 
{ 
    GraphicsDeviceManager graphics; 
    SpriteBatch spriteBatch; 

    private Vector2 vec1 = new Vector2(1, 2); 
    private Vector2 vec2 = new Vector2(2, 3); 
    private Vector2 min; 
    private string timeRefOut1; 
    private string timeRefOut2; 
    private SpriteFont font; 

    public Game1() 
    { 
     graphics = new GraphicsDeviceManager(this); 
     Content.RootDirectory = "Content"; 

     refOut1(); 
     refOut2(); 
    } 

    private Vector2 refOut1() 
    { 
     Vector2 min = Vector2.Min(vec1, vec2); 
     return min; 
    } 

    private Vector2 refOut2() 
    { 
     Vector2.Min(ref vec1, ref vec2, out min); 
     return min; 
    } 

    protected override void Initialize() 
    { 
     const int len = 100000000; 
     Stopwatch stopWatch = new Stopwatch(); 
     stopWatch.Start(); 
     for (int i = 0; i < len; i++) 
     { 
      refOut1(); 
     } 
     stopWatch.Stop(); 

     timeRefOut1 = stopWatch.ElapsedMilliseconds.ToString(); 

     stopWatch.Reset(); 
     stopWatch.Start(); 
     for (int i = 0; i < len; i++) 
     { 
      refOut2(); 
     } 
     stopWatch.Stop(); 

     timeRefOut2 = stopWatch.ElapsedMilliseconds.ToString(); 

     base.Initialize(); 
    } 

    protected override void LoadContent() 
    { 
     spriteBatch = new SpriteBatch(GraphicsDevice); 
     font = Content.Load<SpriteFont>("SpriteFont1"); 
    } 

    protected override void Update(GameTime gameTime) 
    { 
     if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) 
      this.Exit(); 

     base.Update(gameTime); 
    } 

    protected override void Draw(GameTime gameTime) 
    { 
     GraphicsDevice.Clear(Color.CornflowerBlue); 

     spriteBatch.Begin(); 
     spriteBatch.DrawString(font, timeRefOut1, new Vector2(200, 200), Color.White); 
     spriteBatch.DrawString(font, timeRefOut2, new Vector2(200, 300), Color.White); 
     spriteBatch.End(); 

     // TODO: Add your drawing code here 

     base.Draw(gameTime); 
    } 
} 

परिणाम:

यहाँ एक परीक्षण कोड है। नेट 4. एक्सएनए 4.0

इसके अलावा आईएल कोड

.method public hidebysig static void Min(valuetype Microsoft.Xna.Framework.Vector2& value1, 
              valuetype Microsoft.Xna.Framework.Vector2& value2, 
              [out] valuetype Microsoft.Xna.Framework.Vector2& result) cil managed 
{ 
    // Code size  69 (0x45) 
    .maxstack 3 
    IL_0000: ldarg.2 
    IL_0001: ldarg.0 
    IL_0002: ldfld  float32 Microsoft.Xna.Framework.Vector2::X 
    IL_0007: ldarg.1 
    IL_0008: ldfld  float32 Microsoft.Xna.Framework.Vector2::X 
    IL_000d: blt.s  IL_0017 
    IL_000f: ldarg.1 
    IL_0010: ldfld  float32 Microsoft.Xna.Framework.Vector2::X 
    IL_0015: br.s  IL_001d 
    IL_0017: ldarg.0 
    IL_0018: ldfld  float32 Microsoft.Xna.Framework.Vector2::X 
    IL_001d: stfld  float32 Microsoft.Xna.Framework.Vector2::X 
    IL_0022: ldarg.2 
    IL_0023: ldarg.0 
    IL_0024: ldfld  float32 Microsoft.Xna.Framework.Vector2::Y 
    IL_0029: ldarg.1 
    IL_002a: ldfld  float32 Microsoft.Xna.Framework.Vector2::Y 
    IL_002f: blt.s  IL_0039 
    IL_0031: ldarg.1 
    IL_0032: ldfld  float32 Microsoft.Xna.Framework.Vector2::Y 
    IL_0037: br.s  IL_003f 
    IL_0039: ldarg.0 
    IL_003a: ldfld  float32 Microsoft.Xna.Framework.Vector2::Y 
    IL_003f: stfld  float32 Microsoft.Xna.Framework.Vector2::Y 
    IL_0044: ret 
} // end of method Vector2::Min 

और

.method public hidebysig static valuetype Microsoft.Xna.Framework.Vector2 
     Min(valuetype Microsoft.Xna.Framework.Vector2 value1, 
      valuetype Microsoft.Xna.Framework.Vector2 value2) cil managed 
{ 
    // Code size  80 (0x50) 
    .maxstack 3 
    .locals init (valuetype Microsoft.Xna.Framework.Vector2 V_0) 
    IL_0000: ldloca.s V_0 
    IL_0002: ldarga.s value1 
    IL_0004: ldfld  float32 Microsoft.Xna.Framework.Vector2::X 
    IL_0009: ldarga.s value2 
    IL_000b: ldfld  float32 Microsoft.Xna.Framework.Vector2::X 
    IL_0010: blt.s  IL_001b 
    IL_0012: ldarga.s value2 
    IL_0014: ldfld  float32 Microsoft.Xna.Framework.Vector2::X 
    IL_0019: br.s  IL_0022 
    IL_001b: ldarga.s value1 
    IL_001d: ldfld  float32 Microsoft.Xna.Framework.Vector2::X 
    IL_0022: stfld  float32 Microsoft.Xna.Framework.Vector2::X 
    IL_0027: ldloca.s V_0 
    IL_0029: ldarga.s value1 
    IL_002b: ldfld  float32 Microsoft.Xna.Framework.Vector2::Y 
    IL_0030: ldarga.s value2 
    IL_0032: ldfld  float32 Microsoft.Xna.Framework.Vector2::Y 
    IL_0037: blt.s  IL_0042 
    IL_0039: ldarga.s value2 
    IL_003b: ldfld  float32 Microsoft.Xna.Framework.Vector2::Y 
    IL_0040: br.s  IL_0049 
    IL_0042: ldarga.s value1 
    IL_0044: ldfld  float32 Microsoft.Xna.Framework.Vector2::Y 
    IL_0049: stfld  float32 Microsoft.Xna.Framework.Vector2::Y 
    IL_004e: ldloc.0 
    IL_004f: ret 
} // end of method Vector2::Min 

लगता है भूमि के ऊपर अस्थायी वेक्टर के कारण होता है। पुनरावृत्तियों की भयावहता छोटी संख्या के एक आदेश के लिए

टिक की संख्या: इसके अलावा, मैं 1GHz WP 7.5 डिवाइस की कोशिश की।

+1

मुझे लगता है कि * वास्तविक * प्रश्न है, ".NET क्या आरवीओ नहीं करना चाहिए?" – Mehrdad

उत्तर

7

वेक्टर 2 एक संरचना है, जिसका अर्थ यह है कि जब इसे किसी मान के रूप में वापस किया जाता है, तो एक मौजूदा संरचना के संदर्भ को वापस करने के बजाय प्रतिलिपि वापस कर दी जाती है। रेफ/आउट पैरामीटर का उपयोग करके आप इस प्रतिलिपि से बच सकते हैं ताकि न्यूनतम विधि में बनाया गया वेक्टर आपके result चर में सटीक वेक्टर है।

यह उन माइक्रो ऑप्टिमाइज़ेशन में से एक है जो आम तौर पर निराश हो जाते हैं, लेकिन गेम की दुनिया में यह अक्सर पर्याप्त होता है, और ऐसे वातावरण में जहां प्रदर्शन पर्याप्त मायने रखता है, यह थोड़ा कम पठनीय विकल्प के लायक है।

+0

किसी मान प्रकार को आउट/रेफ पैरामीटर में असाइन करना स्थानीय चर से मान को पैरामीटर में "कॉपी" कर रहा है। –

+2

@PeterRitchie संपूर्ण बिंदु यह होगा कि आउट/रेफ पैरामीटर का उपयोग पूरे चर में स्थानीय चर के रूप में किया जाएगा ताकि आपके पास स्थानीय चर से बाहर/ref पैरामीटर की प्रतिलिपि न हो। अन्यथा, हाँ, आप एक अतिरिक्त प्रतिलिपि करेंगे और यह उद्देश्य को हरा देगा। – Servy

+1

आप अभी भी एक चर से दूसरे (पैरामीटर) में मान असाइन कर रहे हैं। असाइनमेंट एक "प्रतिलिपि" ऑपरेशन है; जब तक आप एक वैरिएबल (प्रकार के बावजूद) के लिए मान प्रकार निर्दिष्ट कर रहे हैं, तो आप मान को "कॉपी" कर रहे हैं। –

3

सर्वो द्वारा वर्णित प्रदर्शन प्रभाव के शीर्ष पर एक और अंतर कई "वापसी" मान रखने की क्षमता है: उन्हें सामान्य तरीके से वापस करने की बजाय, आप उन्हें रेफ/var पैरामीटर के रूप में सूचीबद्ध करते हैं।

+2

यह मेरा पहला विचार क्या है, लेकिन वे केवल 1 मान वापस करते हैं। –

+0

@ लुकास - इस मामले में, हाँ, मैं सामान्य मामले के लिए लिख रहा था :) – Attila

संबंधित मुद्दे