2015-02-15 12 views
6

पर निरंतर शाखाओं में रूपांतरण यदि मैं निम्नलिखित कोड के अंतिम दो "if" कथन को एक शाखा रहित राज्य में परिवर्तित करने का तरीका जानने के लिए अटक गया हूं।बयान

int u, x, y; 
x = rand() % 100 - 50; 
y = rand() % 100 - 50; 

u = rand() % 4; 
if (y > x) u = 5; 
if (-y > x) u = 4; 

या, के मामले में ऊपर निकला भी मुश्किल हो सकता है, आप उन पर विचार कर के रूप में:

if (x > 0) u = 5; 
if (y > 0) u = 4; 

मुझे लगता है कि मुझे क्या हो जाता है तथ्य यह है कि उन लोगों के लिए एक else नहीं है पकड़ने वाला। अगर ऐसा होता तो मैं संभवतः एक शाखा रहित abs (या max/min) फ़ंक्शन का एक भिन्नता अनुकूलित कर सकता था।

rand() फ़ंक्शन जो आप देखते हैं वे वास्तविक कोड का हिस्सा नहीं हैं। मैंने उन्हें अपेक्षित श्रेणियों पर संकेत देने के लिए जोड़ा है कि वेरिएबल्स x, y और u संभवतः दो शाखाएं होने पर संभवतः हो सकती हैं।

उद्देश्य के लिए असेंबली मशीन कोड की अनुमति है।

संपादित करें:

बाद braingrinding का एक सा मैं एक साथ काम कर रहे एक शाखा संस्करण डाल करने में कामयाब रहे:

int u, x, y; 
x = rand() % 100 - 50; 
y = rand() % 100 - 50; 

u = rand() % 4; 
u += (4-u)*((unsigned int)(x+y) >> 31); 
u += (5-u)*((unsigned int)(x-y) >> 31); 

दुर्भाग्य पूर्णांक शामिल गणित के कारण, अगर बयान के साथ मूल संस्करण में पता चला है 30% रेंज से तेज हो।

कंपाइलर जानता है कि पार्टी कहां है।

+0

क्या एक्स और वाई कहीं और उपयोग किया जाता है? यदि नहीं, तो उन पंक्तियों में से प्रत्येक भी 'अगर (रैंड()% 2) हो सकता है ... '। –

+1

'u + = (5 - u) * (y> x);'? –

+0

@ ओलिवर चार्ल्सवर्थ मैं देखता हूं। हां, वे कहीं और इस्तेमाल होते हैं। – user2464424

उत्तर

2

[सभी: यह उत्तर इस धारणा के साथ लिखा गया था कि रैंड() पर कॉल समस्या का हिस्सा थे। मैं उस धारणा के तहत नीचे सुधार प्रदान करता हूं। ओपी ने स्पष्ट रूप से स्पष्ट किया कि वह केवल एक्स और वाई के मूल्यों की सीमाओं (और संभवतः वितरण) को बताने के लिए रैंड का उपयोग करता था। अस्पष्ट अगर वह आपके लिए भी मूल्य के लिए था। वैसे भी, उस समस्या के मेरे बेहतर उत्तर का आनंद लें जो उसने वास्तव में नहीं किया था]।

मुझे लगता है कि आप के रूप में इस recoding बेहतर होगा:

int u, x, y; 
x = rand() % 100 - 50; 
y = rand() % 100 - 50; 

if (y > x) u = 5; 
else if (-y > x) u = 4; 
else u = rand() % 4; 

यह पिछले रैंड केवल 1/4 के रूप में अक्सर कहता ओ पी के मूल कोड के रूप में। चूंकि मुझे लगता है कि रैंड (और विभाजन) तुलनात्मक और शाखा की तुलना में अधिक महंगा है, यह एक महत्वपूर्ण बचत होगी।

अपने रैंड जनरेटर प्रत्येक कॉल पर सही मायने में यादृच्छिक बिट्स (जैसे 16) का एक बहुत पैदा करता है, तो एकदम सही ढंग से, आप इसे सिर्फ एक बार फोन कर सकते हैं (मैं मान लिया गया है रैंड विभाजन से ज्यादा महंगा है, YMMV):

int u, x, y, t; 
t = rand() ; 
u = t % 4; 
t = t >> 2; 
x = t % 100 - 50; 
y = (t/100) %100 - 50; 

if (y > x) u = 5; 
else if (-y > x) u = 4; 

मुझे लगता है कि एमएस सी लाइब्रेरी में रैंड फ़ंक्शन इसके लिए पर्याप्त नहीं है यदि आप वास्तव में यादृच्छिक मान चाहते हैं। मुझे अपना कोड कोड करना पड़ा; वैसे भी तेजी से बाहर निकला।

तुम भी एक पारस्परिक (untested) द्वारा विभाजित से छुटकारा मिल सकता, गुणन का उपयोग करके:

int u, x, y; 
unsigned int t; 
unsigned long t2; 
t = rand() ; 
u = t % 4; 

{ // Compute value of x * 2^32 in a long by multiplying. 
    // The (unsigned int) term below should be folded into a single constant at compile time. 
    // The remaining multiply can be done by one machine instruction 
    // (typically 32bits * 32bits --> 64bits) widely found in processors. 
    // The "4" has the same effect as the t = t >> 2 in the previous version 
    t2 = (t * ((unsigned int)1./(4.*100.)*(1<<32)); 
} 
x = (t2>>32)-50; // take the upper word (if compiler won't, do this in assembler) 
{ // compute y from the fractional remainder of the above multiply, 
    // which is sitting in the lower 32 bits of the t2 product 
    y = (t2 mod (1<<32)) * (unsigned int)(100.*(1<<32)); 
} 

if (y > x) u = 5; 
else if (-y > x) u = 4; 

अपने संकलक "सही" निर्देश का उत्पादन नहीं होगा, यह विधानसभा लिखने के लिए सरल होना चाहिए ऐसा करने के लिए कोड।

+0

जबकि मैं पूरी तरह से रैंड() और मॉड्यूलो फ़ंक्शंस के बारे में पूरी तरह से सहमत हूं, प्रदर्शन-महत्वपूर्ण कोड के लिए बिल्कुल सही नहीं है, मैं वास्तव में केवल उन्हें वहां रखता हूं ताकि पाठक को "x" मानों की अपेक्षित सीमा पर एक संकेत दिया जा सके, "वाई" और "यू" चर संभवतः कोड के ऑन-विषय अनुभाग (सबसे महत्वपूर्ण रूप से "यू") के समय पकड़ सकते हैं। असुविधा के बारे में खेद है, मैं वादा करता हूं कि अगली बार मैं और अधिक स्पष्ट हो जाऊंगा। – user2464424

+0

शाखा की स्थिति यादृच्छिक है, यह वास्तव में बहुत महंगी होगी, क्योंकि सीपीयू शाखा भविष्यवाणी करने में मदद करने के लिए शक्तिहीन है। मुझे कल्पना है कि विभाजन के रूप में कम से कम महंगा या कॉल() की अटकलें (अनुमान है, सबूत का समर्थन नहीं किया गया है, हालांकि .. ।) –

+1

सबकुछ के साथ, मापें, मापें, मापें ... और फिर विचार करें कि कार्यान्वयन तकनीक में परिवर्तन होने पर क्या होता है। (यदि शाखाएं अभी भी अपेक्षाकृत महंगे हैं, तो मेरी सभी भिन्नताओं में उन्हें अन्य उत्तरों द्वारा सुझाए गए सशर्त चालों में बदल दिया जा सकता है। –

0

सरणियों सूचकांकों का उपयोग कर कुछ चाल, वे बहुत तेजी से अगर संकलक/सीपीयू एक दर कदम निर्देश 0-1 मान (उदा 86 के "सेटे" और इसी तरह) की तुलना परिणाम कन्वर्ट करने के लिए है हो सकता है।

int ycpx[3]; 

/* ... */ 
ycpx[0] = 4; 
ycpx[1] = u; 
ycpx[2] = 5; 
u = ycpx[1 - (-y <= x) + (y > x)]; 

वैकल्पिक रूप

int v1[2]; 
int v2[2]; 

/* ... */ 
v1[0] = u; 
v1[1] = 5; 
v2[1] = 4; 
v2[0] = v1[y > x]; 
u = v2[-y > x]; 

लगभग अपठनीय ...

नोट: दोनों ही मामलों में सरणी 4 और 5 युक्त तत्वों के प्रारंभ घोषणा और सरणियों में शामिल किया जा सकता स्थिर किया जा सकता है अगर पुनर्वित्त आपके लिए कोई समस्या नहीं है।