सी ++ फ़ाइल में किसी फ़ंक्शन की स्थिति उसके प्रदर्शन को क्यों प्रभावित करती है? विशेष रूप से नीचे दिए गए उदाहरण में हमारे पास दो समान कार्य हैं जिनमें अलग-अलग, लगातार प्रदर्शन प्रोफ़ाइल हैं। कोई इसकी जांच करने और यह निर्धारित करने के लिए कैसे जाता है कि प्रदर्शन इतना अलग क्यों है?सी ++ फ़ाइल में किसी फ़ंक्शन की स्थिति उसके प्रदर्शन को प्रभावित करती है
उदाहरण बहुत सरल है कि हमारे पास दो कार्य हैं: ए और बी। प्रत्येक एक तंग पाश में कई बार चलाया जाता है और अनुकूलित (-O3 -march=corei7-avx
) और समय।
#include <cstdint>
#include <iostream>
#include <numeric>
#include <boost/timer/timer.hpp>
bool array[] = {true, false, true, false, false, true};
uint32_t __attribute__((noinline)) a() {
asm("");
return std::accumulate(std::begin(array), std::end(array), 0);
}
uint32_t __attribute__((noinline)) b() {
asm("");
return std::accumulate(std::begin(array), std::end(array), 0);
}
const size_t WARM_ITERS = 1ull << 10;
const size_t MAX_ITERS = 1ull << 30;
void test(const char* name, uint32_t (*fn)())
{
std::cout << name << ": ";
for (size_t i = 0; i < WARM_ITERS; i++) {
fn();
asm("");
}
boost::timer::auto_cpu_timer t;
for (size_t i = 0; i < MAX_ITERS; i++) {
fn();
asm("");
}
}
int main(int argc, char **argv)
{
test("a", a);
test("b", b);
return 0;
}
कुछ उल्लेखनीय विशेषताएं::
- समारोह ए और बी समान हैं यहाँ कोड है। वे एक ही संचय ऑपरेशन करते हैं और एक ही असेंबली निर्देशों को संकलित करते हैं।
- टाइमिंग शुरू करने से पहले प्रत्येक परीक्षण पुनरावृत्ति में गर्मी की अवधि होती है और कैश को गर्म करने के साथ किसी भी समस्या को खत्म करने से पहले।
जब यह संकलित करने और चलाने है हम दिखा एक ख की तुलना में काफी धीमी है निम्न आउटपुट प्राप्त:
[[email protected]:~/code/mystery] make && ./mystery
g++-4.8 -c -g -O3 -Wall -Wno-unused-local-typedefs -std=c++11 -march=corei7-avx -I/usr/local/include/boost-1_54/ mystery.cpp -o mystery.o
g++-4.8 mystery.o -lboost_system-gcc48-1_54 -lboost_timer-gcc48-1_54 -o mystery
a: 7.412747s wall, 7.400000s user + 0.000000s system = 7.400000s CPU (99.8%)
b: 5.729706s wall, 5.740000s user + 0.000000s system = 5.740000s CPU (100.2%)
हम दो परीक्षणों को उलटने के हैं (यानी फोन test(b)
और फिर test(a)
) एक अभी भी धीमी है ख से:
[[email protected]:~/code/mystery] make && ./mystery
g++-4.8 -c -g -O3 -Wall -Wno-unused-local-typedefs -std=c++11 -march=corei7-avx -I/usr/local/include/boost-1_54/ mystery.cpp -o mystery.o
g++-4.8 mystery.o -lboost_system-gcc48-1_54 -lboost_timer-gcc48-1_54 -o mystery
b: 5.733968s wall, 5.730000s user + 0.000000s system = 5.730000s CPU (99.9%)
a: 7.414538s wall, 7.410000s user + 0.000000s system = 7.410000s CPU (99.9%)
अब हम ++ फ़ाइल सी में कार्यों का स्थान उलटने हैं (एक के ऊपर ख की परिभाषा के लिए कदम) परिणाम उल्टे कर रहे हैं और एक बी की तुलना में तेजी बन जाता है!
[[email protected]:~/code/mystery] make && ./mystery
g++-4.8 -c -g -O3 -Wall -Wno-unused-local-typedefs -std=c++11 -march=corei7-avx -I/usr/local/include/boost-1_54/ mystery.cpp -o mystery.o
g++-4.8 mystery.o -lboost_system-gcc48-1_54 -lboost_timer-gcc48-1_54 -o mystery
a: 5.729604s wall, 5.720000s user + 0.000000s system = 5.720000s CPU (99.8%)
b: 7.411549s wall, 7.420000s user + 0.000000s system = 7.420000s CPU (100.1%)
तो अनिवार्य रूप से सी ++ फ़ाइल के शीर्ष पर जो भी फ़ंक्शन धीमा है, धीमा है।
प्रश्नों के कुछ उत्तर आप हो सकता है:
- कोड संकलित दोनों ए और बी के लिए समान है। Disassembly की जांच की गई है। (रुचि रखने वालों के लिए: http://pastebin.com/2QziqRXR)
- कोड जीसीसी 4.8, जीसीसी 4.8.1 यूबंटू 13.04, उबंटू 13.10, और उबंटू 12.04.03 पर संकलित किया गया था।
- प्रभाव इंटेल सैंडी ब्रिज i7-2600 और इंटेल ज़ीऑन एक्स 5482 सीपीयू पर देखे गए प्रभाव।
ऐसा क्यों होगा? इस तरह की कुछ जांच करने के लिए कौन से टूल्स उपलब्ध हैं?
क्या यह संभव है कि वे अलग-अलग पृष्ठों पर समाप्त हो रहे हैं, और इससे अतिरिक्त काम हो रहा है? मुझे यह अजीब लगता है कि CPU समय सिस्टम माप में है, उपयोगकर्ता नहीं। इसका तात्पर्य है कि यह उपयोगकर्ता कोड लेने का समय नहीं चल रहा है, लेकिन प्रक्रियाओं की ओर से कुछ ओएस स्तर की बात है। –
अंधेरे में एक पूर्ण शॉट के रूप में, मैं सुझाव दूंगा कि पहले सत्र चलने वाले सत्र के परिणामस्वरूप बी सत्र को और भी गर्म किया जाएगा ... (संपादित करें: ओह, आप उलटा हुआ ...) –
@ डेव्स मेरा मानना है कि समय सभी उपयोगकर्ता अंतरिक्ष भूमि में है। लूप गर्मी लूप (माप से पहले) कैश और शाखा भविष्यवाणी को गर्म करने के लिए पर्याप्त होना चाहिए। – Shane