简体   繁体   中英

It`s possible to calculate time complexity of Shader algorithm?

I'm currently attending an algorithm analysis class and we were given group work. The Professor demanded we choose some field in computer science, pick an algorithm and prove the asymptotic limits (at least O(N)).

So me and my colleague chose to do a computer graphics algorithm, more specifically a lighting volume algorithm.

But all the code analysed by algorithm analysis books runs on the CPU. Code produced in OpenGL runs on the GPU, which can not guarantee linearity, since it is made of several other CPUs running in parallel.

Does that behavior influence the calculation? Could someone help me figure out where to start?

This piece of code is extracted from GPU Gems 3: Volumetric Light Scattering as a Post-Process .

float4 main(float2 texCoord : TEXCOORD0) : COLOR0  
{  
  // Calculate vector from pixel to light source in screen space.  
   half2 deltaTexCoord = (texCoord - ScreenLightPos.xy);  
  // Divide by number of samples and scale by control factor.  
  deltaTexCoord *= 1.0f / NUM_SAMPLES * Density;  
  // Store initial sample.  
   half3 color = tex2D(frameSampler, texCoord);  
  // Set up illumination decay factor.  
   half illuminationDecay = 1.0f;  
  // Evaluate summation from Equation 3 NUM_SAMPLES iterations.  
   for (int i = 0; i < NUM_SAMPLES; i++)  
  {  
    // Step sample location along ray.  
    texCoord -= deltaTexCoord;  
    // Retrieve sample at new location.  
   half3 sample = tex2D(frameSampler, texCoord);  
    // Apply sample attenuation scale/decay factors.  
    sample *= illuminationDecay * Weight;  
    // Accumulate combined color.  
    color += sample;  
    // Update exponential decay factor.  
    illuminationDecay *= Decay;  
  }  
  // Output final color with a further scale control factor.  
   return float4( color * Exposure, 1);  
}

I think the asymptotic limit would be a function of the samples. Something that also needs to be taken into account are the 4 physical equations needed to generate the shader. Thanks in advance for all the community help!

The complexity of an algorithm does not change with the number of processing elements (for a finite number of processors). A polynomial time algorithm is polynomial time, whether on the CPU or GPU. To put it another way, n 2 is no different from (n/320) 2 , as "n" approaches infinity.

The complexity of the algorithm doesn't change; the execution time does. But this is true of lots of complexity. Quick sort and merge sort have the same nLog(n) complexity, but quick sort is on average faster in practice.

Asymptotic limits are not the end-all-be-all of performance.

All lines of code implies a constant execution time (they don't imply loops or recursive calls or anything like that). However, the lines inside the loop are executed NUM_SAMPLES times. Therefore, the execution time of one shader invocation is going to be:

O(NumSamples)

Since this shader is executed once per pixel the total execution time is going to be:

O(NumSamples * ResolutionX * ResolutionY)

Keep in mind that Nicol Bolas is right, the complexity of the algorithm hasn't changed, it has the same if it is executed on the CPU, but it would be slower for hardware-related issues.

In a deeper analysis you could analyze the usage of each GPU core and the speedup over the CPU, but in this simple code... It doesn't matter much since usage would probably be very close to 100%. In any case, to analyze this you'll need to understand both GPU hardware architecture and general algorithm costs.

uniform float exposure;
uniform float decay;
uniform float density;
uniform float weight;
uniform vec2 lightPositionOnScreen;
uniform sampler2D myTexture;
const int NUM_SAMPLES = 100 ;
void main()
{   
C1  vec2 deltaTextCoord=vec2(gl_TexCoord[0].st-lightPositionOnScreen.xy);                          
C2      vec2 textCoo = gl_TexCoord[0].st;                                                                         
C3      deltaTextCoord *= 1.0 /  float(NUM_SAMPLES) * density;                                        
C4      float illuminationDecay = 1.0;                                                                                 
n       for(int i=0; i < NUM_SAMPLES ; i++)     {                                          
C5              textCoo -= deltaTextCoord;                                                    
C6          vec4 sample = texture2D(myTexture, textCoo );                        
C7                     sample *= illuminationDecay * weight;                                   
C8              gl_FragColor += sample;                                                      
C9              illuminationDecay *= decay;                                                    
                                                }
C10                 gl_FragColor *= exposure;  
}

f(n) =∑_(i=0)^n〖(C_5+ C_6+ C_7+ C_8+ C_9)〗 + C_1 + C_2 + C_3 + C_4 + C_10

(C_5+ C_6+ C_7+ C_8+ C_9 )=K_1

(C_1 + C_2 + C_3 + C_4 + C_10)=K_2

Therefore: f(n)= Cp* K_1*n+ K_2

Being Cp the number of pixels.

Which is f(n)= θ(n) for each pixel.

@dv1729 Comment really helped in the course of the development of the University Homework.

This Proves the Computer Graphics Algorithms analysis can be very deceptive, because we all know how hard on hardware this kind of post-processing is, but reviewing the code shows us an Asymptotic limit that is indeed very low. The constants here can be very high and the profound math behind physically based volumetric light sccatering, can go unnoticed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM