जावा 8 बार तेजी से std की तुलना में सरणियों के साथ :: C ++ में वेक्टर। मैंने गलत क्या किया?


88

मेरे पास कई बड़े सरणियों के साथ निम्नलिखित जावा कोड है जो कभी भी अपना आकार नहीं बदलते हैं। यह मेरे कंप्यूटर पर 1100 ms में चलता है।

मैंने C ++ में समान कोड लागू किया और उपयोग किया std::vector

C ++ कार्यान्वयन का समय जो ठीक उसी कोड को चलाता है, मेरे कंप्यूटर पर 8800 ms है। मैंने क्या गलत किया, ताकि यह धीरे-धीरे चले?

मूल रूप से कोड निम्नलिखित करता है:

for (int i = 0; i < numberOfCells; ++i) {
        h[i] =  h[i] + 1;
        floodedCells[i] =  !floodedCells[i];
        floodedCellsTimeInterval[i] =  !floodedCellsTimeInterval[i];
        qInflow[i] =  qInflow[i] + 1;
}

यह लगभग 20000 के आकार के साथ विभिन्न सरणियों के माध्यम से पुनरावृत्त करता है।

आप निम्नलिखित लिंक के तहत दोनों कार्यान्वयन पा सकते हैं:

(ऑनडोन पर मैं समय सीमा के कारण केवल 2000 बार के बजाय लूप को 400 बार चला सकता था। लेकिन यहां भी तीन बार का अंतर है)


42
std::vector<bool>अंतरिक्ष को बचाने के लिए प्रति तत्व एक बिट का उपयोग करता है, जिससे बहुत अधिक बिट-शिफ्टिंग होती है। यदि आप गति चाहते हैं, तो आपको इससे दूर रहना चाहिए। std::vector<int>इसके बजाय उपयोग करें ।
मोलबडनीलो

44
@molbdnilo या std :: वेक्टर <char>। वहाँ इतना है कि बर्बाद करने की कोई जरूरत नहीं है ;-)
स्टीफन

7
काफी मजेदार। C ++ संस्करण तेजी से होता है जब कोशिकाओं की संख्या 200 होती है। Cache इलाके?
कप्तान जिराफ

9
भाग II: आप एक अलग वर्ग / संरचना बनाने में बहुत बेहतर होंगे, जिसमें प्रत्येक सदस्य के सरणियों में से एक है और फिर इस संरचना की वस्तुओं का एक ही सरणी है, क्योंकि तब आप वास्तव में केवल एक बार स्मृति के माध्यम से पुनरावृत्ति कर रहे हैं, एक दिशा।
टिमो ज्यूशच

9
@TimoGeusch: जबकि मुझे लगता है h[i] += 1;या (अभी भी बेहतर) ++h[i]की तुलना में अधिक पठनीय है h[i] = h[i] + 1;, मुझे उनके बीच गति में कोई महत्वपूर्ण अंतर देखकर कुछ आश्चर्य होगा। एक कंपाइलर "यह पता लगा सकता है" कि वे दोनों एक ही काम कर रहे हैं, और एक ही कोड या तो उत्पन्न करते हैं (कम से कम अधिकांश सामान्य मामलों में)।
जेरी कॉफिन

जवाबों:


36

यहाँ C ++ संस्करण प्रति-नोड डेटा के साथ एक संरचना में इकट्ठा किया गया है, और उस संरचना का एक एकल वेक्टर उपयोग किया गया है:

#include <vector>
#include <cmath>
#include <iostream>



class FloodIsolation {
public:
  FloodIsolation() :
      numberOfCells(20000),
      data(numberOfCells)
  {
  }
  ~FloodIsolation(){
  }

  void isUpdateNeeded() {
    for (int i = 0; i < numberOfCells; ++i) {
       data[i].h = data[i].h + 1;
       data[i].floodedCells = !data[i].floodedCells;
       data[i].floodedCellsTimeInterval = !data[i].floodedCellsTimeInterval;
       data[i].qInflow = data[i].qInflow + 1;
       data[i].qStartTime = data[i].qStartTime + 1;
       data[i].qEndTime = data[i].qEndTime + 1;
       data[i].lowerFloorCells = data[i].lowerFloorCells + 1;
       data[i].cellLocationX = data[i].cellLocationX + 1;
       data[i].cellLocationY = data[i].cellLocationY + 1;
       data[i].cellLocationZ = data[i].cellLocationZ + 1;
       data[i].levelOfCell = data[i].levelOfCell + 1;
       data[i].valueOfCellIds = data[i].valueOfCellIds + 1;
       data[i].h0 = data[i].h0 + 1;
       data[i].vU = data[i].vU + 1;
       data[i].vV = data[i].vV + 1;
       data[i].vUh = data[i].vUh + 1;
       data[i].vVh = data[i].vVh + 1;
       data[i].vUh0 = data[i].vUh0 + 1;
       data[i].vVh0 = data[i].vVh0 + 1;
       data[i].ghh = data[i].ghh + 1;
       data[i].sfx = data[i].sfx + 1;
       data[i].sfy = data[i].sfy + 1;
       data[i].qIn = data[i].qIn + 1;


      for(int j = 0; j < nEdges; ++j) {
        data[i].flagInterface[j] = !data[i].flagInterface[j];
        data[i].typeInterface[j] = data[i].typeInterface[j] + 1;
        data[i].neighborIds[j] = data[i].neighborIds[j] + 1;
      }
    }

  }

private:

  const int numberOfCells;
  static const int nEdges = 6;
  struct data_t {
    bool floodedCells = 0;
    bool floodedCellsTimeInterval = 0;

    double valueOfCellIds = 0;
    double h = 0;

    double h0 = 0;
    double vU = 0;
    double vV = 0;
    double vUh = 0;
    double vVh = 0;
    double vUh0 = 0;
    double vVh0 = 0;
    double ghh = 0;
    double sfx = 0;
    double sfy = 0;
    double qInflow = 0;
    double qStartTime = 0;
    double qEndTime = 0;
    double qIn = 0;
    double nx = 0;
    double ny = 0;
    double floorLevels = 0;
    int lowerFloorCells = 0;
    bool floorCompleteleyFilled = 0;
    double cellLocationX = 0;
    double cellLocationY = 0;
    double cellLocationZ = 0;
    int levelOfCell = 0;
    bool flagInterface[nEdges] = {};
    int typeInterface[nEdges] = {};
    int neighborIds[nEdges] = {};
  };
  std::vector<data_t> data;

};

int main() {
  std::ios_base::sync_with_stdio(false);
  FloodIsolation isolation;
  clock_t start = clock();
  for (int i = 0; i < 400; ++i) {
    if(i % 100 == 0) {
      std::cout << i << "\n";
    }
    isolation.isUpdateNeeded();
  }
  clock_t stop = clock();
  std::cout << "Time: " << difftime(stop, start) / 1000 << "\n";
}

जीवंत उदाहरण

समय अब ​​जावा संस्करण की गति 2x है। (846 बनाम 1631)।

बाधाओं को जेआईटी ने देखा है कि सभी जगहों पर डेटा तक पहुँचने का कैश जल रहा है, और आपके कोड को तार्किक रूप से समान लेकिन कुशल आदेश में बदल दिया है।

मैं भी stdio तुल्यकालन बंद कर दिया, के रूप में है कि केवल यदि आप मिश्रण की जरूरत है printf/ scanfसी ++ के साथ std::coutऔर std::cin। जैसा कि होता है, आप केवल कुछ मानों को ही प्रिंट करते हैं, लेकिन मुद्रण के लिए C ++ का डिफ़ॉल्ट व्यवहार अतिरेक और अक्षम है।

यदि nEdgesवास्तविक स्थिर मूल्य नहीं है, तो 3 "सरणी" मानों को छीनना होगा struct। यह एक बहुत बड़ा प्रदर्शन हिट नहीं होना चाहिए।

आप structआकार को कम करके, इस प्रकार मेमोरी फ़ुटप्रिंट को कम करके (और इससे कोई फर्क नहीं पड़ता जब तक पहुंच को छांट कर) एक और प्रदर्शन बढ़ाने में सक्षम हो सकता है । लेकिन मैं अनिश्चित हूं।

अंगूठे का एक नियम यह है कि एक एकल कैश मिस एक निर्देश से 100 गुना अधिक महंगा है। आपके डेटा को कैश सुसंगतता के लिए व्यवस्थित करने का बहुत मूल्य है।

यदि डेटा को पुन: व्यवस्थित करना संभव नहीं structहै, तो आप बदले में प्रत्येक कंटेनर के ऊपर अपनी पुनरावृत्ति को बदल सकते हैं।

एक तरफ के रूप में, ध्यान दें कि जावा और सी ++ संस्करणों में कुछ सूक्ष्म अंतर थे। जो मैंने देखा था वह यह था कि जावा संस्करण में "प्रत्येक किनारे के लिए" लूप में 3 चर हैं, जबकि C ++ एक में केवल 2 थे। मैंने अपना जावा से मिलान किया। मुझे नहीं पता कि क्या अन्य हैं।


44

हां, सी ++ संस्करण में कैश एक हथौड़ा लेता है। ऐसा लगता है कि जेआईटी इसे संभालने के लिए बेहतर तरीके से सुसज्जित है।

यदि आप बाहरी परिवर्तन करते हैं for छोटे स्निपेट में isUpdateNeeded () में । अंतर दूर हो जाता है।

नीचे का नमूना 4x स्पीडअप का उत्पादन करता है।

void isUpdateNeeded() {
    for (int i = 0; i < numberOfCells; ++i) {
        h[i] =  h[i] + 1;
        floodedCells[i] =  !floodedCells[i];
        floodedCellsTimeInterval[i] =  !floodedCellsTimeInterval[i];
        qInflow[i] =  qInflow[i] + 1;
        qStartTime[i] =  qStartTime[i] + 1;
        qEndTime[i] =  qEndTime[i] + 1;
    }

    for (int i = 0; i < numberOfCells; ++i) {
        lowerFloorCells[i] =  lowerFloorCells[i] + 1;
        cellLocationX[i] =  cellLocationX[i] + 1;
        cellLocationY[i] =  cellLocationY[i] + 1;
        cellLocationZ[i] =  cellLocationZ[i] + 1;
        levelOfCell[i] =  levelOfCell[i] + 1;
        valueOfCellIds[i] =  valueOfCellIds[i] + 1;
        h0[i] =  h0[i] + 1;
        vU[i] =  vU[i] + 1;
        vV[i] =  vV[i] + 1;
        vUh[i] =  vUh[i] + 1;
        vVh[i] =  vVh[i] + 1;
    }
    for (int i = 0; i < numberOfCells; ++i) {
        vUh0[i] =  vUh0[i] + 1;
        vVh0[i] =  vVh0[i] + 1;
        ghh[i] =  ghh[i] + 1;
        sfx[i] =  sfx[i] + 1;
        sfy[i] =  sfy[i] + 1;
        qIn[i] =  qIn[i] + 1;
        for(int j = 0; j < nEdges; ++j) {
            neighborIds[i * nEdges + j] = neighborIds[i * nEdges + j] + 1;
        }
        for(int j = 0; j < nEdges; ++j) {
            typeInterface[i * nEdges + j] = typeInterface[i * nEdges + j] + 1;
        }
    }

}

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

आदेश बहाल हुआ

जैसा कि स्टीफ़न की टिप्पणी के अनुसार मैंने मूल आकारों का उपयोग करके उन्हें एक संरचना में समूहीकृत करने की कोशिश की। यह इसी तरह से तत्काल कैश दबाव को दूर करता है। परिणाम यह है कि c ++ (CCFLAG -O3) संस्करण जावा संस्करण की तुलना में लगभग 15% तेज है।

न तो कम और न ही अधिक।

#include <vector>
#include <cmath>
#include <iostream>
 
 
 
class FloodIsolation {
    struct item{
      char floodedCells;
      char floodedCellsTimeInterval;
      double valueOfCellIds;
      double h;
      double h0;
      double vU;
      double vV;
      double vUh;
      double vVh;
      double vUh0;
      double vVh0;
      double sfx;
      double sfy;
      double qInflow;
      double qStartTime;
      double qEndTime;
      double qIn;
      double nx;
      double ny;
      double ghh;
      double floorLevels;
      int lowerFloorCells;
      char flagInterface;
      char floorCompletelyFilled;
      double cellLocationX;
      double cellLocationY;
      double cellLocationZ;
      int levelOfCell;
    };
    struct inner_item{
      int typeInterface;
      int neighborIds;
    };

    std::vector<inner_item> inner_data;
    std::vector<item> data;

public:
    FloodIsolation() :
            numberOfCells(20000), inner_data(numberOfCells * nEdges), data(numberOfCells)
   {

    }
    ~FloodIsolation(){
    }
 
    void isUpdateNeeded() {
        for (int i = 0; i < numberOfCells; ++i) {
            data[i].h = data[i].h + 1;
            data[i].floodedCells = !data[i].floodedCells;
            data[i].floodedCellsTimeInterval = !data[i].floodedCellsTimeInterval;
            data[i].qInflow = data[i].qInflow + 1;
            data[i].qStartTime = data[i].qStartTime + 1;
            data[i].qEndTime = data[i].qEndTime + 1;
            data[i].lowerFloorCells = data[i].lowerFloorCells + 1;
            data[i].cellLocationX = data[i].cellLocationX + 1;
            data[i].cellLocationY = data[i].cellLocationY + 1;
            data[i].cellLocationZ = data[i].cellLocationZ + 1;
            data[i].levelOfCell = data[i].levelOfCell + 1;
            data[i].valueOfCellIds = data[i].valueOfCellIds + 1;
            data[i].h0 = data[i].h0 + 1;
            data[i].vU = data[i].vU + 1;
            data[i].vV = data[i].vV + 1;
            data[i].vUh = data[i].vUh + 1;
            data[i].vVh = data[i].vVh + 1;
            data[i].vUh0 = data[i].vUh0 + 1;
            data[i].vVh0 = data[i].vVh0 + 1;
            data[i].ghh = data[i].ghh + 1;
            data[i].sfx = data[i].sfx + 1;
            data[i].sfy = data[i].sfy + 1;
            data[i].qIn = data[i].qIn + 1;
            for(int j = 0; j < nEdges; ++j) {
                inner_data[i * nEdges + j].neighborIds = inner_data[i * nEdges + j].neighborIds + 1;
                inner_data[i * nEdges + j].typeInterface = inner_data[i * nEdges + j].typeInterface + 1;
            }
        }
 
    }
 
    static const int nEdges;
private:
 
    const int numberOfCells;

};
 
const int FloodIsolation::nEdges = 6;

int main() {
    FloodIsolation isolation;
    clock_t start = clock();
    for (int i = 0; i < 4400; ++i) {
        if(i % 100 == 0) {
            std::cout << i << "\n";
        }
        isolation.isUpdateNeeded();
    }

    clock_t stop = clock();
    std::cout << "Time: " << difftime(stop, start) / 1000 << "\n";
}
                                                                              

मेरा परिणाम मूल आकारों के लिए जेरी कॉफिन्स से थोड़ा अलग है। मेरे लिए मतभेद बने हुए हैं। यह अच्छी तरह से मेरा जावा संस्करण हो सकता है, 1.7.0_75।


12
यह एक अच्छा विचार हो सकता है कि उस डेटा को एक संरचना में समूहित करें और सिर्फ एक वेक्टर
स्टीफन

वैसे मैं मोबाइल पर हूं इसलिए मैं माप नहीं कर सकता;; लेकिन एक वेक्टर अच्छा होना चाहिए (आवंटन के मामले में भी)
स्टीफन

1
किसी ++भी क्षमता में मदद का उपयोग करता है? x = x + 1की तुलना में भयंकर रूप से भद्दा लगता है ++x
tadman

3
कृपया गलत शब्द "परिणाम" को ठीक करें। यह मुझे मार रहा है .. :)
fleetC0m

1
यदि पूरा पुनरावृत्त एक ही रजिस्टर में फिट बैठता है, तो प्रतिलिपि बनाना वास्तव में कुछ मामलों में तेजी से अद्यतन हो सकता है। यदि आप जगह में अपडेट कर रहे हैं, तो इसका कारण यह है कि आप बहुत ही अद्यतन मूल्य का उपयोग कर रहे हैं। तो आपके पास Read-after-Write निर्भरता है। यदि आप अपडेट करते हैं, लेकिन केवल पुराने मूल्य की आवश्यकता है, तो वे ऑपरेशन एक-दूसरे पर निर्भर नहीं करते हैं और सीपीयू के पास समानांतर में उन्हें करने के लिए अधिक कमरे हैं, उदाहरण के लिए विभिन्न पाइपलाइनों पर, प्रभावी आईपीसी बढ़ रही है।
पियोट कोक्लाज़कोव्स्की

20

जैसा कि @Stefan ने @ CaptainGiraffe के उत्तर पर एक टिप्पणी में अनुमान लगाया है, आप वैक्टर की एक संरचना के बजाय एक वेक्टर के पैटर्न का उपयोग करके काफी लाभ प्राप्त करते हैं। सही कोड इस तरह दिखता है:

#include <vector>
#include <cmath>
#include <iostream>
#include <time.h>

class FloodIsolation {
public:
    FloodIsolation() :
            h(0),
            floodedCells(0),
            floodedCellsTimeInterval(0),
            qInflow(0),
            qStartTime(0),
            qEndTime(0),
            lowerFloorCells(0),
            cellLocationX(0),
            cellLocationY(0),
            cellLocationZ(0),
            levelOfCell(0),
            valueOfCellIds(0),
            h0(0),
            vU(0),
            vV(0),
            vUh(0),
            vVh(0),
            vUh0(0),
            vVh0(0),
            ghh(0),
            sfx(0),
            sfy(0),
            qIn(0),
            typeInterface(nEdges, 0),
            neighborIds(nEdges, 0)
    {
    }

    ~FloodIsolation(){
    }

    void Update() {
        h =  h + 1;
        floodedCells =  !floodedCells;
        floodedCellsTimeInterval =  !floodedCellsTimeInterval;
        qInflow =  qInflow + 1;
        qStartTime =  qStartTime + 1;
        qEndTime =  qEndTime + 1;
        lowerFloorCells =  lowerFloorCells + 1;
        cellLocationX =  cellLocationX + 1;
        cellLocationY =  cellLocationY + 1;
        cellLocationZ =  cellLocationZ + 1;
        levelOfCell =  levelOfCell + 1;
        valueOfCellIds =  valueOfCellIds + 1;
        h0 =  h0 + 1;
        vU =  vU + 1;
        vV =  vV + 1;
        vUh =  vUh + 1;
        vVh =  vVh + 1;
        vUh0 =  vUh0 + 1;
        vVh0 =  vVh0 + 1;
        ghh =  ghh + 1;
        sfx =  sfx + 1;
        sfy =  sfy + 1;
        qIn =  qIn + 1;
        for(int j = 0; j < nEdges; ++j) {
            ++typeInterface[j];
            ++neighborIds[j];
        }       
    }

private:

    static const int nEdges = 6;
    bool floodedCells;
    bool floodedCellsTimeInterval;

    std::vector<int> neighborIds;
    double valueOfCellIds;
    double h;
    double h0;
    double vU;
    double vV;
    double vUh;
    double vVh;
    double vUh0;
    double vVh0;
    double ghh;
    double sfx;
    double sfy;
    double qInflow;
    double qStartTime;
    double qEndTime;
    double qIn;
    double nx;
    double ny;
    double floorLevels;
    int lowerFloorCells;
    bool flagInterface;
    std::vector<int> typeInterface;
    bool floorCompleteleyFilled;
    double cellLocationX;
    double cellLocationY;
    double cellLocationZ;
    int levelOfCell;
};

int main() {
    std::vector<FloodIsolation> isolation(20000);
    clock_t start = clock();
    for (int i = 0; i < 400; ++i) {
        if(i % 100 == 0) {
            std::cout << i << "\n";
        }

        for (auto &f : isolation)
            f.Update();
    }
    clock_t stop = clock();
    std::cout << "Time: " << difftime(stop, start) / 1000 << "\n";
}

VC ++ 2015 CTP से संकलक के साथ संकलित, का उपयोग करके -EHsc -O2b2 -GL -Qpar, मुझे इस तरह के परिणाम मिलते हैं:

0
100
200
300
Time: 0.135

जी ++ के साथ संकलन एक परिणाम है जो थोड़ा धीमा है:

0
100
200
300
Time: 0.156

उसी हार्डवेयर पर, जावा 8u45 से कंपाइलर / जेवीएम का उपयोग करने पर मुझे परिणाम मिलते हैं:

0
100
200
300
Time: 181

यह VC ++ से संस्करण की तुलना में लगभग 35% धीमा है, और जी ++ से संस्करण की तुलना में लगभग 16% धीमा है।

यदि हम पुनरावृत्तियों की संख्या को वांछित 2000 तक बढ़ा देते हैं, तो अंतर केवल 3% तक गिर जाता है, यह सुझाव देता है कि इस मामले में C ++ के लाभ का एक हिस्सा केवल तेजी से लोड हो रहा है (जावा के साथ एक बारहमासी समस्या), वास्तव में निष्पादन में ही नहीं। यह मुझे इस मामले में आश्चर्यचकित नहीं करता है - गणना (पोस्ट किए गए कोड में) की गणना इतनी तुच्छ है कि मुझे संदेह है कि अधिकांश कंपाइलर इसे अनुकूलित करने के लिए पूरी तरह से कर सकते हैं।


1
सुधार के लिए अभी भी जगह है, हालांकि यह सबसे अधिक संभावना प्रदर्शन को प्रभावित नहीं करेगा: बूलियन चर को समूहीकृत करना (सामान्य रूप से एक ही प्रकार के चर को समूहीकृत करना)।
स्टीफन

1
@stefan: वहाँ है, लेकिन मैं जानबूझकर कोड के किसी भी भारी अनुकूलन को करने से बच रहा था, और इसके बजाय मूल कार्यान्वयन में सबसे स्पष्ट समस्याओं को दूर करने के लिए न्यूनतम आवश्यक (लगभग) कर रहा था। अगर मैं वास्तव में अनुकूलन करना चाहता था, तो मैं #pragma ompएक लूप चलना सुनिश्चित करने के लिए एक (और) एक छोटा सा काम जोड़ूंगा। यह एक ~ Nx स्पीडअप प्राप्त करने के लिए काफी न्यूनतम काम करेगा, जहां N उपलब्ध प्रोसेसर कोर की संख्या है।
जेरी कॉफ़िन

अच्छी बात। इस प्रश्न के उत्तर के लिए यह पर्याप्त है
स्टीफन

कैसे 181 समय इकाइयाँ 35% धीमी हैं 0.135 समय इकाइयों और 16% धीमी 0.156 समय इकाइयों की तुलना में? क्या आपका मतलब है कि जावा संस्करण की अवधि 0.181 है?
jamesdlin

1
@jamesdlin: वे विभिन्न इकाइयों का उपयोग कर रहे हैं (इस तरह छोड़ दिया, क्योंकि यह है कि मूल में चीजें कैसे थीं)। C ++ कोड सेकंड में समय देता है, लेकिन जावा कोड मिलीसेकंड में समय देता है।
जेरी कॉफ़िन

9

मुझे संदेह है कि यह मेमोरी के आवंटन के बारे में है।

मैं सोच रहा हूं कि Javaप्रोग्राम स्टार्टअप पर एक बड़ा सन्निहित ब्लॉक पकड़ लेता हैC++ बिट्स और टुकड़ों के लिए ओएस पूछता है क्योंकि यह साथ जाता है।

परीक्षण में उस सिद्धांत को डालने के लिए मैंने C++संस्करण में एक संशोधन किया और यह अचानक Javaसंस्करण की तुलना में थोड़ा तेज चलने लगा :

int main() {
    {
        // grab a large chunk of contiguous memory and liberate it
        std::vector<double> alloc(20000 * 20);
    }
    FloodIsolation isolation;
    clock_t start = clock();
    for (int i = 0; i < 400; ++i) {
        if(i % 100 == 0) {
            std::cout << i << "\n";
        }
        isolation.isUpdateNeeded();
    }
    clock_t stop = clock();
    std::cout << "Time: " << (1000 * difftime(stop, start) / CLOCKS_PER_SEC) << "\n";
}

उपदेश वेक्टर के बिना रनटाइम :

0
100
200
300
Time: 1250.31

उपदेश वेक्टर के साथ रनटाइम :

0
100
200
300
Time: 331.214

Javaसंस्करण के लिए रनटाइम :

0
100
200
300
Time: 407

वैसे आप वास्तव में उस पर भरोसा नहीं कर सकते। डेटा FloodIsolationअभी भी कहीं और आवंटित किया जा सकता है।
स्टेफन

@stefan फिर भी एक दिलचस्प परिणाम।
कप्तान जिराफ

@CaptainGiraffe यह है, मैंने यह नहीं कहा कि यह बेकार है;;
स्टीफन

2
@stefan मैं इसे एक समाधान के रूप में प्रस्तावित नहीं कर रहा हूं, केवल जांच कर रहा हूं कि मुझे क्या समस्या है। ऐसा लगता है कि इसका कैशिंग से कोई लेना-देना नहीं है, लेकिन C ++ RTS जावा से कैसे भिन्न है।
गैलिक

1
@ गालिक यह हमेशा कारण नहीं होता है, हालांकि यह आपके मंच पर उस बड़े प्रभाव को देखने के लिए काफी दिलचस्प है। आइडोन पर, मैं आपके परिणाम को पुन: उत्पन्न नहीं कर सकता (जैसा कि ऐसा लगता है, आवंटित ब्लॉक का पुन: उपयोग नहीं किया गया है): ideone.com/im4NMO हालांकि, सैंपल्स सॉल्यूशन के वेक्टर में अधिक सुसंगत प्रदर्शन प्रभाव होता है: ideone.com/b0VWSN
stefan
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.