2009-06-29 4 views
16

हम एक प्रदर्शन महत्वपूर्ण अनुप्रयोग को .NET पर माइग्रेट करना चाहते हैं और यह पता लगाएं कि सी # संस्करण प्रोसेसर के आधार पर Win32/C की तुलना में 30% से 100% धीमा है (मोबाइल T7200 प्रोसेसर पर अधिक अंतर)। मेरे पास कोड का एक बहुत ही सरल नमूना है जो इसे प्रदर्शित करता है। संक्षिप्तता के लिए मैं सिर्फ सी संस्करण दिखाऊंगा - सी # एक सीधा अनुवाद है:सी # (काफी धीमी) और Win32/C के बीच प्रदर्शन अंतर क्यों?

#include "stdafx.h" 
#include "Windows.h" 

int array1[100000]; 
int array2[100000]; 

int Test(); 

int main(int argc, char* argv[]) 
{ 
    int res = Test(); 

    return 0; 
} 

int Test() 
{ 
    int calc,i,k; 
    calc = 0; 

    for (i = 0; i < 50000; i++) array1[i] = i + 2; 

    for (i = 0; i < 50000; i++) array2[i] = 2 * i - 2; 

    for (i = 0; i < 50000; i++) 
    { 
     for (k = 0; k < 50000; k++) 
     { 
      if (array1[i] == array2[k]) calc = calc - array2[i] + array1[k]; 
      else calc = calc + array1[i] - array2[k]; 
     } 
    } 
    return calc; 
} 

अगर हम के लिए Win32 में disassembly को देखो 'शेष' हमने:

35:    else calc = calc + array1[i] - array2[k]; 
004011A0 jmp   Test+0FCh (004011bc) 
004011A2 mov   eax,dword ptr [ebp-8] 
004011A5 mov   ecx,dword ptr [ebp-4] 
004011A8 add   ecx,dword ptr [eax*4+48DA70h] 
004011AF mov   edx,dword ptr [ebp-0Ch] 
004011B2 sub   ecx,dword ptr [edx*4+42BFF0h] 
004011B9 mov   dword ptr [ebp-4],ecx 

(यह है डिबग लेकिन मेरे साथ सहन) में

अनुकूलित C# अनुकूलित exe पर CLR डीबगर का उपयोग कर संस्करण के लिए disassembly:

    else calc = calc + pev_tmp[i] - gat_tmp[k]; 
000000a7 mov   eax,dword ptr [ebp-4] 
000000aa mov   edx,dword ptr [ebp-8] 
000000ad mov   ecx,dword ptr [ebp-10h] 
000000b0 mov   ecx,dword ptr [ecx] 
000000b2 cmp   edx,dword ptr [ecx+4] 
000000b5 jb   000000BC 
000000b7 call  792BC16C 
000000bc add   eax,dword ptr [ecx+edx*4+8] 
000000c0 mov   edx,dword ptr [ebp-0Ch] 
000000c3 mov   ecx,dword ptr [ebp-14h] 
000000c6 mov   ecx,dword ptr [ecx] 
000000c8 cmp   edx,dword ptr [ecx+4] 
000000cb jb   000000D2 
000000cd call  792BC16C 
000000d2 sub   eax,dword ptr [ecx+edx*4+8] 
000000d6 mov   dword ptr [ebp-4],eax 

संभवतः प्रदर्शन अंतर का कारण कई और निर्देश।

तो 3 प्रश्न वास्तव में:

  1. 2 कार्यक्रमों के लिए सही disassembly तलाश में हूं या उपकरण मुझे गुमराह कर रहे हैं?

  2. तो उत्पन्न निर्देश की संख्या में अंतर क्या अंतर है का कारण नहीं है?

  3. क्या हम संभवतः इसके बारे में क्या कर सकते हैं अन्य की तुलना में एक देशी DLL में हमारे सभी प्रदर्शन महत्वपूर्ण कोड रहते हैं।

अग्रिम धन्यवाद स्टीव

पुनश्च मैं एक तरह बिल्डिंग प्रदर्शन महत्वपूर्ण देशी अनुप्रयोगों 'हम्म एक संयुक्त एमएस/इंटेल संगोष्ठी हकदार कुछ करने के लिए हाल ही में आमंत्रण प्राप्त था ...

+0

क्या आप असेंबली निर्देशों के बीच सभी न्यूलाइन हटा सकते हैं। –

+0

हमेशा की तरह, यह देखने के लिए प्रोफाइल करें कि सबसे अधिक प्रदर्शन हिट कितना खर्च करता है। (ऐसा कोई तरीका नहीं है कि हम देख सकें कि आपके कोड में समय क्या है, इसलिए हमें पूछने में कोई बात नहीं है। इसके बजाय एक प्रोफाइलर से पूछें) इसके अलावा, एक सरल चाल आपके सी # कोड को एनजेन के माध्यम से चलाने के लिए हो सकती है। यह प्रदर्शन को थोड़ा सा बढ़ावा देना चाहिए। – jalf

+0

सीएलआर का कौन सा संस्करण आप तुलना कर रहे हैं। जहां तक ​​मुझे पता है, .NET 3.5 SP1 जेआईटी कंपाइलर पुराने लोगों की तुलना में अधिक कुशल है। X64 जेआईटी ऑप्टिमाइज़र x86 एक से अधिक आक्रामक है। –

उत्तर

13

मेरा मानना ​​है कि आप सरणी पर सीमाओं के चेक के परिणाम देख रहे हैं। आप असुरक्षित कोड का उपयोग कर सीमाओं से बच सकते हैं।

मेरा मानना ​​है कि JITer छोरों कि array.Length और से बचने के सीमा की जाँच करने के लिए ऊपर जाना जैसे प्रतिमानों की पहचान कर सकते हैं, लेकिन यह नहीं लगता है अपने कोड की तरह है कि utilizate कर सकते हैं।

+9

मुझे इनमें से बहुत से सेब-संतरे "समान दिखते हैं कोड "खिलौना कोड के साथ perf तुलना में प्रयास करता है। फिर भी मैं तुलनीय गुणवत्ता के पूर्ण, उत्पाद-गुणवत्ता कोड के साथ नकारात्मक तुलना कभी नहीं देखता। शायद क्योंकि सी # वास्तव में धीमी नहीं है। –

+1

@ ग्रेग डी: मैं सहमत हूं। मैं लगभग उच्च प्रदर्शन, वैज्ञानिक उन्मुख संख्यात्मक प्रसंस्करण पर लगभग विशेष रूप से काम करता हूं। सी # में एक बहुत अलग perf है। सी ++ की तुलना में प्रोफाइल, हालांकि, प्रोफाइलिंग महत्वपूर्ण है - लेकिन सामान्य रूप से, आप C#+ को सही प्रोफाइलिंग और कोड में समायोजन के साथ सी ++ जितनी तेजी से प्राप्त कर सकते हैं। –

+2

@ ग्रेग, रीड - प्रबंधित कोड प्रदर्शन के साथ देखे जाने वाले अधिकांश मुद्दे इस तरह के CPU समय के आसपास नहीं हैं, लेकिन लोड समय और मेमोरी पदचिह्न जैसी चीजें हैं। इनके लिए, सी ++ का अभी भी एक बड़ा फायदा है (हालांकि खराब प्रोग्रामर आसानी से उस लाभ को अस्वीकार कर सकते हैं :) – Michael

0

मुझे यकीन है कि सी के लिए अनुकूलन सी # से अलग है। इसके अलावा आपको कम से कम प्रदर्शन की धीमी गति से उम्मीद करनी होगी। .NET ढांचे के साथ एप्लिकेशन में एक और परत जोड़ता है।

व्यापार बंद एक तेज मात्रा में गति (क्या होना चाहिए) के लिए अधिक तेज़ विकास, विशाल पुस्तकालय और कार्य है।

2

सी # सीमा

जाँच जब सी # असुरक्षित कोड में गणना हिस्सा यह प्रदर्शन करता है और साथ ही देशी कार्यान्वयन चल कर रहा है?

18

मेरा मानना ​​है कि इस कोड में आपका मुख्य मुद्दा आपके सरणी पर जांच कर रहा है।

आप सी # में असुरक्षित कोड का उपयोग करने के लिए स्विच, और सूचक गणित का उपयोग करते हैं, आप एक ही (या संभावित तेज) कोड प्राप्त करने के लिए सक्षम होना चाहिए।

यह वही समस्या previously discussed in detail in this question थी।

6

जैसा कि अन्य ने कहा है, पहलुओं में से एक जांच की सीमा है। सरणी पहुंच के संदर्भ में आपके कोड में कुछ अनावश्यकता भी है। मैं करने के लिए भीतरी ब्लॉक बदलकर कुछ हद तक प्रदर्शन में सुधार करने में कामयाब रहे है: परिवर्तन ~ 8.8s को ~ 5s से नीचे गिरा दिया

int tmp1 = array1[i]; 
int tmp2 = array2[k]; 
if (tmp1 == tmp2) 
{ 
    calc = calc - array2[i] + array1[k]; 
} 
else 
{ 
    calc = calc + tmp1 - tmp2; 
} 

कि कुल समय।

+0

@ जोन: शायद मुझे कुछ याद आ रहा है, लेकिन मैं आपके संस्करण और ओपी के संस्करण के बीच किसी भी महत्वपूर्ण प्रदर्शन अंतर को माप नहीं सकता। वास्तव में, मैं प्रदर्शन पर इस तरह के प्रभाव के लिए इस तरह के कम से कम परिवर्तन की अपेक्षा नहीं करता। –

+0

न तो मैं विशेष रूप से, लेकिन यह निश्चित रूप से मेरे लिए .NET 3.5 और 4.0b1 दोनों पर करता है।कंसोल ऐप के रूप में 32 बिट विस्टा पर/ओ +/डीबग के साथ संकलित। मैंने आई और के चर के दायरे को भी बदल दिया है, लेकिन मुझे संदेह है कि यह महत्वपूर्ण है। –

+0

(मैंने यह सुनिश्चित करने के लिए पर्याप्त समय का परीक्षण किया है कि यह सिर्फ एक झलक नहीं है, बीटीडब्ल्यू :) –

1

यदि आपके एप्लिकेशन के प्रदर्शन महत्वपूर्ण पथ में पूरी तरह से अनचेक सरणी प्रसंस्करण शामिल है, तो मैं आपको सलाह देता हूं कि इसे सी # में फिर से लिखना न पड़े।

लेकिन फिर भी, अगर आपके आवेदन पहले से ही भाषा एक्स में ठीक काम करता है, मैं तुम्हें भाषा वाई

क्या आप फिर से लिखने से हासिल करना चाहते हैं में यह फिर से लिखने के लिए नहीं की सलाह देंगे? कम से कम, उच्च प्रदर्शन अनुभागों के लिए अपने पहले से डीबग किए गए सी कोड का उपयोग करके और एक अच्छा यूजर इंटरफेस या नवीनतम समृद्ध .NET पुस्तकालयों के साथ सुविधाजनक एकीकरण प्राप्त करने के लिए सी # का उपयोग करके मिश्रित भाषा समाधान पर गंभीर विचार दें।

A longer answer on a possibly related theme.

4

बस मस्ती के लिए, मैं दृश्य स्टूडियो 2010 में सी # में इस निर्माण की कोशिश की, और JITed disassembly पर एक दृष्टि डाली:

    else 
         calc = calc + array1[i] - array2[k]; 
000000cf mov   eax,dword ptr [ebp-10h] 
000000d2 add   eax,dword ptr [ebp-14h] 
000000d5 sub   eax,edx 
000000d7 mov   dword ptr [ebp-10h],eax 

वे में घबराना के लिए सुधार की एक संख्या बनाया सीएलआर का 4.0।

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