c++ क्या सी++ इंटर्स की तुलना में उपयोग करने के लिए धीमे हैं?




सी++ प्रोग्राम्स (6)

आम तौर पर, एक enum का उपयोग प्रदर्शन के लिए बिल्कुल कोई फर्क नहीं पड़ता है। आपने इसका परीक्षण कैसे किया?

मैंने अभी परीक्षण किया है। मतभेद शुद्ध शोर हैं।

अभी, मैंने दोनों संस्करणों को असेंबलर में संकलित किया है। प्रत्येक से मुख्य कार्य यहां दिया गया है:

पूर्णांक

LFB1778:
        pushl   %ebp
LCFI11:
        movl    %esp, %ebp
LCFI12:
        subl    $8, %esp
LCFI13:
        movl    $65535, %edx
        movl    $1, %eax
        call    __Z41__static_initialization_and_destruction_0ii
        leave
        ret

खिलाड़ी

LFB1774:
        pushl   %ebp
LCFI10:
        movl    %esp, %ebp
LCFI11:
        subl    $8, %esp
LCFI12:
        movl    $65535, %edx
        movl    $1, %eax
        call    __Z41__static_initialization_and_destruction_0ii
        leave
        ret

माइक्रो-बेंचमार्क पर प्रदर्शन के संबंध में किसी भी बयान को आधार देना खतरनाक है। डेटा को स्कूइंग करने वाले बहुत से अपरिपक्व कारक हैं।

यह वास्तव में एक साधारण समस्या है:

मैं एक गो प्रोग्राम प्रोग्रामिंग कर रहा हूँ। क्या मुझे बोर्ड को QVector<int> या QVector<Player> साथ प्रस्तुत करना चाहिए

enum Player
{
    EMPTY = 0,
    BLACK = 1,
    WHITE = 2
};

मुझे लगता है कि निश्चित रूप से, पूर्णांक की बजाय प्लेयर का उपयोग धीमा हो जाएगा। लेकिन मुझे आश्चर्य है कि कितना अधिक, क्योंकि मेरा मानना ​​है कि enum का उपयोग करना बेहतर कोडिंग है।

मैंने खिलाड़ियों को असाइन करने और तुलना करने के संबंध में कुछ परीक्षण किए हैं ( int विपरीत)

QVector<int> vec;
vec.resize(10000000);
int size = vec.size();


for(int i =0; i<size; ++i)
{
    vec[i] = 0;
}


for(int i =0; i<size; ++i)
{
    bool b = (vec[i] == 1);
}


QVector<Player> vec2;
vec2.resize(10000000);
int size = vec2.size();


for(int i =0; i<size; ++i)
{
    vec2[i] = EMPTY;
}


for(int i =0; i<size; ++i)
{
    bool b = (vec2[i] == BLACK);
}

असल में, यह केवल 10% धीमी है। क्या जारी रखने से पहले मुझे कुछ और पता होना चाहिए?

धन्यवाद!

संपादित करें: 10% अंतर मेरी कल्पना का एक चित्र नहीं है, यह क्यूटी और क्यूवीक्टर के लिए विशिष्ट प्रतीत होता है। जब मैं std :: वेक्टर का उपयोग करता हूं, तो गति वही होती है


Enums कोई धीमा नहीं होना चाहिए। वे पूर्णांक के रूप में लागू कर रहे हैं।


एनाम्स संकलन समय (पूर्णांक अक्षरों के रूप में enum स्थिरांक, पूर्णांक चर के रूप में enum चर) के रूप में पूरी तरह से हल कर रहे हैं, इनका उपयोग करने में कोई गति दंड नहीं है।

आम तौर पर औसत गणना में अंतर्निहित प्रकार int से अधिक नहीं होगा (जब तक कि आप इसे बहुत बड़े स्थिरांक में न रखें); तथ्यों में, §7.2 ¶ 5 पर यह स्पष्ट रूप से कहा गया है:

एक गणना का अंतर्निहित प्रकार एक अभिन्न प्रकार है जो गणना में परिभाषित सभी गणक मूल्यों का प्रतिनिधित्व कर सकता है। यह कार्यान्वयन-परिभाषित किया गया है जो अभिन्न प्रकार को गणना के लिए अंतर्निहित प्रकार के रूप में प्रयोग किया जाता है, सिवाय इसके कि अंतर्निहित प्रकार int से बड़ा नहीं होगा जब तक कि एक गणक का मूल्य int या unsigned int में फिट नहीं हो सकता है

जब आप उचित होते हैं तो आपको गणनाओं का उपयोग करना चाहिए क्योंकि वे आमतौर पर कोड को पढ़ने और बनाए रखने के लिए आसान बनाते हैं (क्या आपने कभी "जादू संख्याओं" से भरा प्रोग्राम डीबग करने का प्रयास किया है?: :S )।

आपके परिणामों के लिए: संभवतः आपकी टेस्ट पद्धति सामान्य स्थिति में उतार-चढ़ाव को ध्यान में रखती है जब आप "सामान्य" मशीनों पर कोड चलाते हैं; क्या आपने कई (100+) बार परीक्षण चलाने और अपने समय के औसत और मानक विचलन की गणना करने की कोशिश की है? परिणाम संगत होना चाहिए: साधनों के बीच का अंतर दो मानक विचलनों के आरएसएस 2 से 1 या 2 गुना बड़ा नहीं होना चाहिए (मान लीजिए, सामान्य रूप से, उतार-चढ़ाव के लिए गॉसियन वितरण)।

एक और जांच जो आप कर सकते हैं वह उत्पन्न असेंबली कोड की तुलना करना है (जी ++ के साथ आप इसे -S स्विच के साथ प्राप्त कर सकते हैं)।

  1. "सामान्य" पीसी पर आपके पास चलने वाले अन्य कार्यों, कैश / रैम / वीएम राज्य की वजह से कुछ अनिश्चित उतार-चढ़ाव होते हैं ...
  2. रूट सम स्क्वायर, वर्ग मानक विचलन के योग की वर्ग जड़।

खैर, मैंने कुछ परीक्षण किए और पूर्णांक और enum रूपों के बीच बहुत अंतर नहीं था। मैंने एक चार रूप भी जोड़ा जो लगातार 6% तेज था (जो आश्चर्यजनक नहीं है क्योंकि यह कम स्मृति का उपयोग कर रहा है)। तब मैंने सिर्फ वेक्टर की बजाय एक चार सरणी का उपयोग किया और यह 300% तेज था! चूंकि हमें यह नहीं दिया गया है कि क्यूवीक्टर क्या है, यह मेरे द्वारा उपयोग किए गए std :: वेक्टर की बजाय सरणी के लिए एक रैपर हो सकता है।

यहां मेरे द्वारा उपयोग किया गया कोड, देव स्टूडियो 2005 में मानक रिलीज विकल्पों का उपयोग करके संकलित किया गया है। ध्यान दें कि मैंने टाइम लूप को एक छोटी राशि बदल दी है क्योंकि प्रश्न में कोड को कुछ भी अनुकूलित नहीं किया जा सकता है (आपको असेंबली कोड देखना होगा) ।

#include <windows.h>
#include <vector>
#include <iostream>

using namespace std;

enum Player
{
    EMPTY = 0,
    BLACK = 1,
    WHITE = 2
};


template <class T, T search>
LONGLONG TimeFunction ()
{
  vector <T>
    vec;

  vec.resize (10000000);

  size_t
    size = vec.size ();

  for (size_t i = 0 ; i < size ; ++i)
  {
      vec [i] = static_cast <T> (rand () % 3);
  }

  LARGE_INTEGER
    start,
    end;

  QueryPerformanceCounter (&start);

  for (size_t i = 0 ; i < size ; ++i)
  {
    if (vec [i] == search)
    {
      break;
    }
  }

  QueryPerformanceCounter (&end);

  return end.QuadPart - start.QuadPart;
}

LONGLONG TimeArrayFunction ()
{
  size_t
    size = 10000000;

  char
    *vec = new char [size];

  for (size_t i = 0 ; i < size ; ++i)
  {
      vec [i] = static_cast <char> (rand () % 3);
  }

  LARGE_INTEGER
    start,
    end;

  QueryPerformanceCounter (&start);

  for (size_t i = 0 ; i < size ; ++i)
  {
    if (vec [i] == 10)
    {
      break;
    }
  }

  QueryPerformanceCounter (&end);

  delete [] vec;

  return end.QuadPart - start.QuadPart;
}

int main ()
{
  cout << "   Char form = " << TimeFunction <char, 10> () << endl;
  cout << "Integer form = " << TimeFunction <int, 10> () << endl;
  cout << " Player form = " << TimeFunction <Player, static_cast <Player> (10)> () << endl;
  cout << "  Array form = " << TimeArrayFunction () << endl;
}

यदि आप उदाहरण के लिए विजुअल स्टूडियो का उपयोग करते हैं तो आप एक साधारण परियोजना बना सकते हैं जहां आपके पास है

     a=Player::EMPTY;

और यदि आप राइट क्लिक करें "डिस्सेप्लिब्स पर जाएं" कोड होगा

mov         dword ptr [a],0

तो कंपाइलर enum के मान को प्रतिस्थापित करता है, और आमतौर पर यह किसी भी ओवरहेड उत्पन्न नहीं करेगा।


कंपाइलर को enum को पूर्णांक में परिवर्तित करना चाहिए। वे संकलन समय पर रेखांकित होते हैं, इसलिए एक बार आपका प्रोग्राम संकलित हो जाने पर, यह बिल्कुल वही होना चाहिए जैसा आपने स्वयं पूर्णांक का उपयोग किया था।

यदि आपका परीक्षण अलग-अलग परिणाम उत्पन्न करता है, तो परीक्षण के साथ कुछ भी हो सकता है। या तो वह, या आपका कंपाइलर अजीब व्यवहार कर रहा है।





performance