C++20 कई नए कार्यों को पेश करता है जैसे कि std::popcount, मैं इंटेल इंट्रिंसिक

मैंने दोनों विकल्पों को संकलित किया - कंपाइलर एक्सप्लोरर कोड में देखा जा सकता है:

  1. Intel के AVX2 आंतरिक का उपयोग करना
  2. std::popcount और GCC संकलक ध्वज का उपयोग करना "-mavx2"

ऐसा लगता है कि एसटीडी के टेम्पलेट में उपयोग किए जाने वाले प्रकार के चेक के अलावा जेनरेट असेंबली कोड समान है।

OS अज्ञेयवादी कोड और समान अनुकूलन के संदर्भ में - क्या यह मान लेना सही है कि std::popcount और उपयुक्त कंपाइलर वेक्टर ऑप्टिमाइज़ेशन फ़्लैग का उपयोग सीधे इंट्रिनिक्स का उपयोग करने से बेहतर है?

धन्यवाद।

2
joepol 5 जिंदा 2021, 17:39
ध्यान दें कि popcnt निर्देश AVX2 का हिस्सा नहीं है। यह POPCNT इंस्ट्रक्शन एक्सटेंशन का हिस्सा है, और AVX2 के पेश होने से पहले, Nehalem आर्किटेक्चर के बाद से सभी Intel प्रोसेसर पर उपलब्ध है।
 – 
Jason R
5 जिंदा 2021, 17:57
आप जेनरेट असेंबली की जांच कर सकते हैं। उदाहरण के लिए, जीसीसी ने मेरे मामले में -march=native और -O2 के साथ popcnt जेनरेट किया: Godbolt.org/z/x3e7Wa। (बस समझ में नहीं आता कि eax को पहले क्यों शून्य किया जाता है; popcnt को rax की संपूर्ण सामग्री को प्रतिस्थापित करना चाहिए, या नहीं करना चाहिए?)
 – 
Daniel Langr
5 जिंदा 2021, 18:27
यदि आप कुछ कार्यान्वयन की जांच करते हैं, तो libstdc++ जीसीसी से एसटीएल उर्फ ​​और libc++ एलएलवीएम/क्लैंग से एसटीएल उर्फ, आप देखते हैं कि वे सीधे इंट्रिनिक्स को कॉल नहीं करते हैं।
 – 
JVApen
5 जिंदा 2021, 21:50
2
गंतव्य रजिस्टर पर popcnt की झूठी निर्भरता है।
 – 
aqrit
5 जिंदा 2021, 23:48
उस लिंक के लिए धन्यवाद; मुझे इस समस्या के बारे में पता नहीं था और यह काफी दिलचस्प है।
 – 
Daniel Langr
6 जिंदा 2021, 08:34

1 उत्तर

सबसे बढ़िया उत्तर

तकनीकी रूप से नहीं। (लेकिन व्यावहारिक रूप से, हाँ)। C++ मानक केवल popcount के व्यवहार को निर्दिष्ट करता है, न कि कार्यान्वयन को (देखें [bit.count])।

कार्यान्वयनकर्ताओं को वह करने की अनुमति है जो वे इस व्यवहार को प्राप्त करना चाहते हैं, जिसमें popcnt आंतरिक का उपयोग करना शामिल है, लेकिन वे थोड़ी देर लूप भी लिख सकते हैं:

int set_bits = 0;
while(x)
{
   if (x & 1)
      ++set_bits;
   x >>= 1;
}
return set_bits;

यह [bit.count] पर मानक में संपूर्ण शब्द है:

template<class T>
constexpr int popcount(T x) noexcept;

बाधाएं: T एक अहस्ताक्षरित पूर्णांक प्रकार है ([basic.fundamental])।
रिटर्न: x के मान में 1 बिट्स की संख्या।

वास्तविक रूप से? कंपाइलर लेखक बहुत स्मार्ट हैं और जितना संभव हो सके इंट्रिनिक्स का उपयोग करने के लिए इसे अनुकूलित करेंगे। उदाहरण के लिए, gcc's कार्यान्वयन काफी हद तक अनुकूलित प्रतीत होता है।

5
AndyG 5 जिंदा 2021, 22:23
मैं उलझन में हूं। आप नहीं से शुरू करते हैं, लेकिन फिर आपकी बाकी पोस्ट मूल रूप से हां पर समाप्त होती है। मेरा मतलब है, सी ++ मानक के तहत, int x = 7+3; को कानूनी रूप से असेंबली में लूप के रूप में लागू करने की अनुमति है, लेकिन आप लोगों को पूर्णांक जोड़ने के लिए इंट्रिनिक्स या असेंबली का उपयोग करने के लिए कहते हुए नहीं देखते हैं, है ना?
 – 
Yakk - Adam Nevraumont
5 जिंदा 2021, 22:19
@ Yakk-AdamNevraumont: मुझे लगता है कि आप मुझसे भी बेहतर जानते हैं कि इसका उत्तर "तकनीकी रूप से नहीं, लेकिन व्यावहारिक रूप से हां" है।
 – 
AndyG
5 जिंदा 2021, 22:21
1
मैं सिर्फ इतना कह रहा हूं कि शायद आपको नहीं के बजाय हां से शुरू करना चाहिए;) कोई गुमराह हो सकता है।
 – 
Yakk - Adam Nevraumont
5 जिंदा 2021, 22:21
उह, हार्डवेयर popcnt उपलब्ध होने पर पॉपकाउंट if(__x == 0) return 0; क्लैंग के साथ बुरी तरह से संकलित होता है, वास्तव में popcnt से FLAGS की जाँच करता है और एक बेकार cmov करता है। godbolt.org/z/KqjPe3। मुझे लगता है कि यह जीसीसी के फॉलबैक बिथैक के आसपास ब्रांचिंग के लायक हो सकता है, लेकिन जीसीसी अभी भी वहां cmov का उपयोग करता है!
 – 
Peter Cordes
6 जिंदा 2021, 08:47
1
Libc++ में वह __x==0 शामिल नहीं है जो संकलक के लिए चीजों को बदतर बनाता है; क्लैंग -stdlib=libc++ अच्छा है godbolt.org/z/8eo64c (लेकिन कोशिश नहीं करता पॉपकंट आउटपुट झूठी निर्भरता से बचें जो स्काईलेक के माध्यम से एसएनबी पर मौजूद है, आइस लेक तक तय नहीं है। क्लैंग आमतौर पर झूठी निर्भरता के साथ लापरवाह होता है, जो उन मामलों में निर्देशों को सहेजता है जहां वे कोई समस्या पैदा नहीं करते हैं।) मुझे लगता है कि __x==0 चेक क्लैंग के __builtin_popcnt के ऑटो-वेक्टराइजेशन को भी हरा देगा (एवीएक्स 2 उपलब्ध होने पर सरणियों पर।)
 – 
Peter Cordes
6 जिंदा 2021, 08:58