मेरे टुकड़े टुकड़े में यह स्थिति इतनी धीमी क्यों है?


19

मैंने वेबजीएल ( इस एसओ उत्तर पर आधारित ) में कुछ एफपीएस-मापने वाला कोड सेट किया है और अपने विखंडन शेडर के प्रदर्शन के साथ कुछ विषमताओं की खोज की है। कोड 1024x1024 कैनवस पर एक एकल क्वाड (या बल्कि दो त्रिकोण) को प्रस्तुत करता है, इसलिए सभी जादू टुकड़े टुकड़े करने वाले में होता है।

इस सरल shader पर विचार करें (GLSL; शीर्ष shader सिर्फ एक पास-थ्रू है):

// some definitions

void main() {
    float seed = uSeed;
    float x = vPos.x;
    float y = vPos.y;

    float value = 1.0;

    // Nothing to see here...

    gl_FragColor = vec4(value, value, value, 1.0);
}

तो यह सिर्फ एक सफेद कैनवास प्रदान करता है। यह मेरी मशीन पर लगभग 30 एफपीएस है।

अब संख्या क्रंचिंग को रैंप करें और स्थिति-निर्भर शोर के कुछ सप्तक के आधार पर प्रत्येक टुकड़े की गणना करें:

void main() {
    float seed = uSeed;
    float x = vPos.x;
    float y = vPos.y;

    float value = 1.0;

      float noise;
      for ( int j=0; j<10; ++j)
      {
        noise = 0.0;
        for ( int i=4; i>0; i-- )
        {
            float oct = pow(2.0,float(i));
            noise += snoise(vec2(mod(seed,13.0)+x*oct,mod(seed*seed,11.0)+y*oct))/oct*4.0;
        }
      }

      value = noise/2.0+0.5;

    gl_FragColor = vec4(value, value, value, 1.0);
}

यदि आप उपरोक्त कोड चलाना चाहते हैं, तो मैं इस कार्यान्वयन काsnoise उपयोग कर रहा हूं ।

यह एफपीएस को कुछ इस तरह नीचे लाता है 7. जो समझ में आता है।

अब अजीब हिस्सा है ... चलो प्रत्येक 16 टुकड़ों में से केवल एक को शोर के रूप में गणना करते हैं और दूसरों को सफेद छोड़ देते हैं, निम्नलिखित स्थिति में शोर गणना को लपेटकर:

if (int(mod(x*512.0,4.0)) == 0 && int(mod(y*512.0,4.0)) == 0)) {
    // same noise computation
}

आप यह बहुत तेजी से होने की उम्मीद करेंगे, लेकिन यह अभी भी केवल 7 एफपीएस है।

एक और परीक्षण के लिए, आइए इसके बजाय पिक्सेल को निम्न सशर्त से फ़िल्टर करें:

if (x > 0.5 && y > 0.5) {
    // same noise computation
}

यह पहले की तरह ही सटीक पिक्सेल पिक्सल की संख्या देता है, लेकिन अब हम लगभग 30 एफपीएस तक वापस आ गए हैं।

यहाँ क्या हो रहा है? क्या पिक्सल्स के 16 वें हिस्से को फिल्टर करने के लिए दो तरीके नहीं, ठीक उसी संख्या में चक्र देने चाहिए? और क्यों धीमी के रूप में सभी पिक्सल को शोर के रूप में धीमा करने के लिए एक है?

बोनस प्रश्न: मैं इस बारे में क्या कर सकता हूं? वहाँ भयानक प्रदर्शन के आसपास काम करने के लिए किसी भी तरह से करता है, तो मैं वास्तव में है है केवल कुछ ही महंगा टुकड़े के साथ अपने कैनवास छींटेदार करना चाहते हैं?

(बस यह सुनिश्चित करने के लिए, मैंने पुष्टि की है कि वास्तविक मॉडुलो अभिकलन फ्रेम दर को प्रभावित नहीं करता है, हर 16 वें पिक्सेल को सफेद के बजाय काले रंग में रेंडर करके।)

जवाबों:


22

पिक्सेल को छोटे वर्गों में विभाजित किया जाता है (हार्डवेयर पर कितना बड़ा निर्भर करता है) और एक ही सिमड पाइपलाइन में एक साथ गणना की जाती है । (सिमड के प्रकार की संरचना)

यह पाइपलाइन (जिसमें विक्रेता के आधार पर कई अलग-अलग नाम हैं: वारप्स, वेवफ्रोंट्स) लॉकस्टेप में प्रत्येक पिक्सेल / टुकड़े के लिए संचालन को निष्पादित करेगा। इसका मतलब यह है कि अगर 1 पिक्सेल को गणना करने की आवश्यकता है, तो सभी पिक्सेल इसकी गणना करेंगे और जिन्हें परिणाम की आवश्यकता नहीं है, वे इसे फेंक देंगे।

यदि सभी टुकड़े एक shader के माध्यम से एक ही पथ का अनुसरण करते हैं तो अन्य शाखाओं को निष्पादित नहीं किया जाएगा।

इसका मतलब है कि हर 16 वें पिक्सेल की गणना करने की आपकी पहली विधि सबसे खराब स्थिति होगी।

यदि आप अभी भी अपनी छवि को आकार देना चाहते हैं, तो बस एक छोटी बनावट के लिए प्रस्तुत करें और फिर इसे अपस्केल करें।


5
एक छोटी बनावट और अपसर्पिंग के लिए प्रस्तुत करना इसे करने का एक अच्छा तरीका है। लेकिन अगर किसी कारण से आपको वास्तव में बड़ी बनावट के हर 16 वें पिक्सेल पर लिखने की आवश्यकता होती है, तो प्रत्येक 16 वें पिक्सेल प्लस छवि लोड / स्टोर के लिए एक कंपाटेटर का उपयोग करके रेंडर को लक्ष्य में लिखने के लिए स्टोर करना एक अच्छा विकल्प हो सकता है।
नाथन रीड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.