cancel
Showing results for 
Search instead for 
Did you mean: 

Archives Discussions

spectral
Adept II

SIMD & conditional expressions

Optimization questions with float4 ?

Hi,

I have some code that currently use 'float' and would like to use 'float4'. But, there is a condition into this function. Is there a solution for this kind of case ?

I join the code, but how will react the 'sqrt' with a negative value or zero value ! Do you think that there is a faster way to do this (Less instruction, lesss divergence) ?

Thanks

 

 

float fresnel_dielectric(float cosi, float eta) { cosi = clamp(cosi, -1.f, 1.f); float c = fabs(cosi); float g = eta * eta - 1 + c * c; if (g > 0) { g = sqrt(g); float A = (g - c) / (g + c); float B = (c * (g + c) - 1) / (c * (g - c) + 1); return 0.5f * A * A * (1 + B * B); } return 1.f; // TIR (no refracted component) } float4 fresnel_dielectric4(float cosi, float4 eta) { cosi = clamp(cosi, -1.f, 1.f); float c = fabs(cosi); float4 g = eta * eta - 1 + c * c; g = sqrt(g); float4 A = (g - c) / (g + c); float4 B = (c * (g + c) - 1) / (c * (g - c) + 1); float4 fresnel 0.5f * A * A * (1 + B * B); return (float4)((g.x > 0) ? fresnel.x : 1.f, (g.x > 0) ? fresnel.x : 1.f, (g.x > 0) ? fresnel.x : 1.f, (g.x > 0) ? fresnel.x : 1.f) }

0 Likes
7 Replies
himanshu_gautam
Grandmaster

viewon01,

why can't you check each element in g(float4 ) just like you are doing for the non-vectorized version?

You can use ternary/select operators instead of if-else. They don't cause a conditional clause switch.

0 Likes

Thanks but,

I don't want to check each element, it request 4 operations !

I already use the ternary operator in the last line of 'fresnel_dielectric4'.

But I can't for 'g' ... because :

a) what give sqrt(X) if x < 0 ?

b) I also want to compute 'fresnel' in a SIMD way (Mainly for CPU)

Right ?

0 Likes

OpenCL's sqrt should behave as c99's sqrt which says:

The sqrt functions compute the nonnegative square root of x. A domain error occurs if the argument is less than zero.

So if you cannot guarantee positive number in sqrt, i guess checking them individually is a must.

 

0 Likes

It is why I afraid of this 😛

Because it require to extract SIMD data into a float, then check it for x,y,z,w...

Finally using SIMD can be more expensive than not using it !

0 Likes

as of your code, maybe you could create two new variables float4 g_m_c = g-c; and float4 g_p_c = g+c; and set A = g_m_c/g_p_c; and B = mad(c,g_p_c,-1)/mad(c,g_m_c,1); (you forgot a '=' before 0.5f when declaring fresnel). I don't know if it would increase performance.

why you test the 'x' components 4 times? Shouldn't you test 'x', 'y', 'z' and 'w' components of g?

about cosi, do you really need a clamp?

about eta, what range of values should it take?

0 Likes
notzed
Challenger

You're after the relational operators (see opencl spec 9.6.5), and the select operator.  See below.

They work just like the trinary operator except that all paths are evaluated explicitly and you can use any width of input.

It shouldn't matter that any result is NaN along the way since it is just discarded.  SIMD processors have to be used in this way for parallelism, so they should behave as you'd expec.  i.e. the processor isn't going to crack a sad just because you gave it invalid data in one path.

The compiler might already be doing the select conversion for you, fwiw (well, if your code was correct, you only ever test for g.x and only ever use use freshnel.x in your result).

 

int4 cmp = isgreater(g, (float4)0); g = sqrt(g); float4 A = (g-c) / ( g + c); etc. float4 fresnel = 0.5f * A * A ...; and finally return select((float4)1, fresnel, cmp);

0 Likes

Perfect,

It is exactly what I was searching for !

Thanks Notzed

0 Likes