2013-08-04 7 views
8

जब निम्नलिखित कोडकंसोल आउटपुट क्रम धीमा मल्टी-थ्रेडेड कार्यक्रम

#include <iostream> 
#include <vector> 
#include <thread> 
#include <chrono> 
#include <mutex> 

std::mutex cout_mut; 

void task() 
{ 
    for(int i=0; i<10; i++) 
    { 
     double d=0.0; 
     for(size_t cnt=0; cnt<200000000; cnt++) d += 1.23456; 

     std::lock_guard<std::mutex> lg(cout_mut); 
     std::cout << d << "(Help)" << std::endl; 
     //  std::cout << "(Help)" << d << std::endl; 
    } 
} 

int main() 
{ 
    std::vector<std::thread> all_t(std::thread::hardware_concurrency()); 

    auto t_begin = std::chrono::high_resolution_clock::now(); 

    for(auto& t : all_t) t = std::thread{task}; 
    for(auto& t : all_t) t.join(); 

    auto t_end = std::chrono::high_resolution_clock::now(); 

    std::cout << "Took : " << (t_end - t_begin).count() << std::endl; 
} 

MinGW के तहत 4.8.1 यह मेरा बॉक्स पर अमल करने के लिए मोटे तौर पर 2.5 सेकंड लेता है संकलन। यह लगभग task फ़ंक्शन को एकल-थ्रेडेड रूप से निष्पादित करने में लगभग समय लगता है।

हालांकि, जब मैं बीच में लाइन uncomment और इसलिए पहले लाइन पूरी बात अब 8-9 सेकंड लेता है (कि, जब मैं जिस क्रम में d और "(Help)"std::cout लिए लिखा जाता है का आदान-प्रदान होता है) बाहर टिप्पणी।

स्पष्टीकरण क्या है?

मैंने फिर से परीक्षण किया और पाया कि मुझे केवल MinGW-build x32-4.8.1-win32-dwarf-rev3 के साथ समस्या है, लेकिन MinGW बिल्ड x64-4.8.1-posix-seh-rev3 के साथ नहीं। मेरे पास 64-बिट मशीन है। 64-बिट कंपाइलर के साथ दोनों संस्करणों में तीन सेकंड लगते हैं। हालांकि, 32-बिट कंपाइलर का उपयोग करते हुए, समस्या बनी हुई है (और रिलीज/डीबग संस्करण भ्रम के कारण नहीं है)।

+1

यह किसी भी तरह हो सकता था कि आप से तेजी से समय मिला एक रिलीज बिल्ड और डीबग बिल्ड से धीमा समय? मैं को स्वैप द्वारा कोई महत्वपूर्ण अंतर नहीं मिला, जीसीसी 4.7.2/4.8.1, क्लैंग 3.2/3.3 (सभी लिनक्स) के साथ। लेकिन रिलीज के निर्माण के लिए मुझे लगभग 2 सेकंड मिलते हैं और डीबग के लिए मुझे लगभग 8 मिलते हैं। विशेष रूप से अनुपात के समान (Windows पर, किसी अन्य मशीन पर) देख रहे हैं। –

+0

नहीं, यह एक डीबग/रिलीज मुद्दा नहीं है; कृपया उपरोक्त मेरा संपादन देखें। –

+0

यह 64-बिट के लिए 32-बिट और एसएसई 2 के लिए x87 fpu का अंतर लगता है। 32-बिट कंपाइलर 'डबल' ऑपरेशंस के x87 निर्देश कोड उत्पन्न कर सकता है (धीमा)। – yohjp

उत्तर

1

इसमें बहु-थ्रेडिंग के साथ कुछ लेना देना नहीं है। यह लूप अनुकूलन की एक समस्या है। जब संकलित और मार डाला और साथ

#include <iostream> 
#include <chrono> 
#include <mutex> 

int main() 
{ 
    auto t_begin = std::chrono::high_resolution_clock::now(); 
    for(int i=0; i<2; i++) 
    { 
     double d=0.0; 
     for(int j=0; j<100000; j++) d += 1.23456; 
     std::mutex mutex; 
     std::lock_guard<std::mutex> lock(mutex); 
#ifdef SLOW 
     std::cout << 'a' << d << std::endl; 
#else 
     std::cout << d << 'a' << std::endl; 
#endif 
    } 
    auto t_end = std::chrono::high_resolution_clock::now(); 
    std::cout << "Took : " << (static_cast<double>((t_end - t_begin).count())/1000.0) << std::endl; 
} 

:

उत्पादन होता है: मैं इस मुद्दे का प्रदर्शन कुछ minimalistic प्राप्त करने के लिए मूल कोड पुन: व्यवस्थित है

a123456 
a123456 
Took : 931 
123456a 
123456a 
Took : 373 

अंतर के अधिकांश समय में आंतरिक लूप के लिए उत्पन्न असेंबली कोड द्वारा समझाया गया है: तेज़ मामला सीधे xmm0 में जमा होता है जबकि धीमा मामला xmm1 में जमा होता है - जिससे 2 अतिरिक्त movsd instru ctions।

अब, जब '-ftree लूप रेखीय' विकल्प के साथ संकलित:

g++ -std=c++11 -ftree-loop-linear -DSLOW -o slow -O3 b.cpp -lpthread ; g++ -std=c++11 -ftree-loop-linear -o fast -O3 b.cpp -lpthread ; ./slow ; ./fast 

उत्पादन हो जाता है:

a123456 
a123456 
Took : 340 
123456a 
123456a 
Took : 346 
संबंधित मुद्दे