मान लें कि हम प्रदर्शन निगरानी के लिए टीएससी का उपयोग करने की कोशिश कर रहे हैं और हम निर्देश पुनर्निर्माण को रोकना चाहते हैं।rdtscp, rdtsc के बीच अंतर: स्मृति और cpuid/rdtsc?
1:rdtscp
एक serializing कॉल है
ये हमारे विकल्प हैं। यह rdtscp पर कॉल के चारों ओर पुनरावृत्ति रोकता है।
__asm__ __volatile__("rdtscp; " // serializing read of tsc
"shl $32,%%rdx; " // shift higher 32 bits stored in rdx up
"or %%rdx,%%rax" // and or onto rax
: "=a"(tsc) // output to tsc variable
:
: "%rcx", "%rdx"); // rcx and rdx are clobbered
हालांकि, rdtscp
नए CPUs पर ही उपलब्ध है। तो इस मामले में हमें rdtsc
का उपयोग करना होगा। लेकिन rdtsc
गैर-क्रमबद्ध है, इसलिए अकेले इसका उपयोग करने से सीपीयू इसे पुन: व्यवस्थित करने से नहीं रोकेगा।
2:
तो हम पुनर्व्यवस्था को रोकने के लिए इन दो विकल्पों में से किसी का उपयोग कर सकते यह cpuid
और फिर rdtsc
के लिए एक कॉल है। cpuid
एक धारावाहिक कॉल है।
volatile int dont_remove __attribute__((unused)); // volatile to stop optimizing
unsigned tmp;
__cpuid(0, tmp, tmp, tmp, tmp); // cpuid is a serialising call
dont_remove = tmp; // prevent optimizing out cpuid
__asm__ __volatile__("rdtsc; " // read of tsc
"shl $32,%%rdx; " // shift higher 32 bits stored in rdx up
"or %%rdx,%%rax" // and or onto rax
: "=a"(tsc) // output to tsc
:
: "%rcx", "%rdx"); // rcx and rdx are clobbered
3: इस मार-पीट की सूची में memory
साथ rdtsc
के लिए एक कॉल, जो पुन: क्रम रोकता है
__asm__ __volatile__("rdtsc; " // read of tsc
"shl $32,%%rdx; " // shift higher 32 bits stored in rdx up
"or %%rdx,%%rax" // and or onto rax
: "=a"(tsc) // output to tsc
:
: "%rcx", "%rdx", "memory"); // rcx and rdx are clobbered
// memory to prevent reordering
3 विकल्प के लिए मेरे समझ इस प्रकार है:
बनाना कॉल __volatile__
ऑप्टिमाइज़र को एएसएम को हटाने या इसे किसी भी निर्देश में ले जाने से रोकता है जिसे एएसएम के परिणामों (या इनपुट को बदलने) की आवश्यकता हो सकती है। हालांकि यह अभी भी असंबंधित परिचालनों के संबंध में इसे स्थानांतरित कर सकता है। तो __volatile__
पर्याप्त नहीं है।
बताएं कि कंपाइलर मेमोरी को गिरफ्तार किया जा रहा है: : "memory")
। "memory"
क्लॉबर का अर्थ है कि जीसीसी एएमएम में समान स्मृति सामग्री के बारे में कोई धारणा नहीं कर सकता है, और इस प्रकार इसके आसपास पुन: व्यवस्थित नहीं होगा।
तो मेरी प्रश्न हैं:
- 1:
__volatile__
और"memory"
सही की मेरी समझ है? - 2: क्या दूसरी दो कॉल एक ही काम करते हैं?
- 3:
"memory"
का उपयोग करना एक और धारावाहिक निर्देश का उपयोग करने से कहीं अधिक सरल दिखता है। दूसरे विकल्प पर तीसरे विकल्प का उपयोग क्यों करेंगे?
आप कंपाइलर द्वारा उत्पन्न निर्देशों की पुनरावृत्ति को भ्रमित करने लगते हैं, जिसे आप 'अस्थिर' और 'मेमोरी' का उपयोग करके और प्रोसेसर द्वारा निष्पादित निर्देशों की पुनरावृत्ति (आदेश निष्पादन_ का उर्फ _out) का उपयोग करके टालना कर सकते हैं, जिसे आप ' cpuid'। – hirschhornsalz
@hirschhornsalz लेकिन क्लॉबर सूची में 'मेमोरी' नहीं होगी प्रोसेसर को निर्देशों को फिर से चलाने से रोकें? मेमोरी बाड़ की तरह 'स्मृति' कार्य नहीं करता है? –
या शायद क्लॉबर सूची में 'मेमोरी' केवल जीसीसी को उत्सर्जित है, और परिणामस्वरूप मशीन कोड प्रोसेसर को इसका खुलासा नहीं करता है? –