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




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

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

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

मैं एक गो प्रोग्राम प्रोग्रामिंग कर रहा हूँ। क्या मुझे बोर्ड को 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 :: वेक्टर का उपयोग करता हूं, तो गति वही होती है


आम तौर पर, एक 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

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


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

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


खैर, मैंने कुछ परीक्षण किए और पूर्णांक और 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;
}

यह कार्यान्वयन निर्भर है, और यह enums और ints के लिए अलग-अलग प्रदर्शन और या तो एक ही या अलग असेंबली कोड के लिए काफी संभव है, हालांकि यह संभवतः उप-उपनिवेशीय कंपाइलर का संकेत है। अंतर पाने के कुछ तरीके हैं:

  • QVector कुछ आश्चर्यजनक करने के लिए आपके enum प्रकार पर विशेष हो सकता है।
  • enum int को संकलित नहीं किया जाता है, लेकिन "कुछ अभिन्न प्रकार int से बड़ा नहीं है"। Int का QVector some_integral_type के QVector से भिन्न रूप से विशिष्ट हो सकता है।
  • यहां तक ​​कि यदि क्यूवीक्टर विशेष नहीं है, तो संकलक कुछ_इनटेग्राल_टाइप को संरेखित करने की तुलना में स्मृति में इन्स को संरेखित करने का बेहतर काम कर सकता है, जिससे आप अधिकतर कैश मिस दर की ओर अग्रसर होते हैं जब आप enums के vector या some_integral_type पर लूप करते हैं।




performance