performance - रकम - हिंदी नाटक और रंगमंच बुक




Memcpy() नाटकीय रूप से हर 4 केबी की गति क्यों गति करता है? (2)

मैंने memcpy() की गति का परीक्षण किया memcpy() I * 4KB पर नाटकीय रूप से गति की बूंदों को देखते हुए। नतीजा निम्नानुसार है: वाई-अक्ष गति (एमबी / सेकेंड) है और एक्स-अक्ष memcpy() लिए बफर का आकार है, जो 1 केबी से 2 एमबी तक बढ़ रहा है। सबफिगर 2 और सबफिगुर 3 1 केबी-150 केबी और 1 केबी -32 केबी के हिस्से का विवरण देता है।

वातावरण:

सीपीयू: इंटेल (आर) ज़ीऑन (आर) सीपीयू ई 5620 @ 2.40GHz

ओएस: 2.6.35-22-जेनेरिक # 33-उबंटू

जीसीसी कंपाइलर झंडे: -ओ 3-एमएसई 4 -DINTEL_SSE4 -Wall -std = c99

मुझे लगता है कि यह कैश से संबंधित होना चाहिए, लेकिन मुझे निम्नलिखित कैश-असभ्य मामलों से कोई कारण नहीं मिल रहा है:

चूंकि इन दो मामलों के प्रदर्शन में गिरावट असभ्य लूपों के कारण होती है जो कैश में बिखरे हुए बाइट्स को पढ़ते हैं, जिससे कैश लाइन के बाकी स्थान को बर्बाद कर दिया जाता है।

मेरा कोड यहाँ है:

void memcpy_speed(unsigned long buf_size, unsigned long iters){
    struct timeval start,  end;
    unsigned char * pbuff_1;
    unsigned char * pbuff_2;

    pbuff_1 = malloc(buf_size);
    pbuff_2 = malloc(buf_size);

    gettimeofday(&start, NULL);
    for(int i = 0; i < iters; ++i){
        memcpy(pbuff_2, pbuff_1, buf_size);
    }   
    gettimeofday(&end, NULL);
    printf("%5.3f\n", ((buf_size*iters)/(1.024*1.024))/((end.tv_sec - \
    start.tv_sec)*1000*1000+(end.tv_usec - start.tv_usec)));
    free(pbuff_1);
    free(pbuff_2);
}

अद्यतन करें

@usr, @ChrisW और @Loror से सुझावों को ध्यान में रखते हुए, मैंने परीक्षण को और सटीक रूप से रेडिड किया और नीचे दिया गया ग्राफ परिणाम दिखाता है। बफर आकार 26 केबी से 38 केबी तक है, और मैंने इसे हर दूसरे 64 बी (26 केबी, 26 केबी +64 बी, 26 केबी + 128 बी, ......, 38 केबी) का परीक्षण किया। प्रत्येक परीक्षण लगभग 0.15 सेकेंड में 100,000 बार लूप करता है। दिलचस्प बात यह है कि ड्रॉप न केवल 4 केबी सीमा में होता है, बल्कि 4 * i + 2 KB में भी आता है, जिसमें बहुत कम गिरावट आयाम होता है।

पुनश्च

@ लीयर ने ड्रॉप को भरने का एक तरीका दिया, जिसमें 2 केबी डमी बफर को pbuff_1 और pbuff_2 बीच pbuff_2 । यह काम करता है, लेकिन मुझे लीर के स्पष्टीकरण के बारे में निश्चित नहीं है।


चूंकि आप कई बार लूपिंग कर रहे हैं, मुझे लगता है कि मैप किए जा रहे पृष्ठों के बारे में तर्क अप्रासंगिक हैं। मेरी राय में आप जो देख रहे हैं वह है हार्डवेयर प्रीफेचर का प्रभाव पृष्ठ सीमा पार करने के लिए तैयार नहीं है (संभावित रूप से अनावश्यक) पृष्ठ दोषों का कारण नहीं है।


मुझे उम्मीद है कि ऐसा इसलिए है क्योंकि:

  • जब ब्लॉक आकार 4KB एकाधिक होता है, तो malloc ओ / एस से नए पृष्ठों को आवंटित करता है।
  • जब ब्लॉक आकार 4KB एकाधिक नहीं होता है, तो malloc इसकी (पहले से आवंटित) ढेर से एक सीमा आवंटित करता है।
  • जब पृष्ठों को ओ / एस से आवंटित किया जाता है तो वे 'ठंड' होते हैं: पहली बार उन्हें छूना बहुत महंगा होता है।

मेरा अनुमान है कि, यदि आप पहले gettimeofday से पहले एक एकल memcpy करते हैं तो वह आवंटित स्मृति 'गर्म' होगा और आप इस समस्या को नहीं देख पाएंगे। प्रारंभिक memcpy करने के बजाय, प्रत्येक आवंटित 4KB पृष्ठ में एक बाइट भी लिखना पृष्ठ को पूर्व-गर्म करने के लिए पर्याप्त हो सकता है।

आमतौर पर जब मैं आपके जैसे प्रदर्शन परीक्षण चाहता हूं तो मैं इसे इस प्रकार कोड करता हूं:

// Run in once to pre-warm the cache
runTest();
// Repeat 
startTimer();
for (int i = count; i; --i)
  runTest();
stopTimer();

// use a larger count if the duration is less than a few seconds
// repeat test 3 times to ensure that results are consistent




cpu-cache