POV-Ray : Newsgroups : povray.general : A couple parser performance issues/optimizations. : Re: A couple parser performance issues/optimizations. Server Time
26 Apr 2024 04:47:00 EDT (-0400)
  Re: A couple parser performance issues/optimizations.  
From: Bald Eagle
Date: 8 Oct 2017 10:05:01
Message: <web.59da2fc231ae2f125cafe28e0@news.povray.org>
Very nice.
Thanks for noticing this issue - I'll have to re-think the way I comment my
code.

I rewrote your scene to do the timing in SDL and compare the elapsed times for
each method.
For large scenes with many slow objects and loops, this may help people
investigate "Why is my scene SO SLOW?"

This once again (although in a different way) highlights the macro vs function
approach discussed in the documentation.






//--- Equivalent coding using macro defining function
//    for faster parsing. Demo slow comments. WFP Oct 6, 2017
//  Edited to record elapsed times in SDL using "now" directive
//  and compare for different methods
#version 3.7;
//------------------------------------------
// SDL for spiral distance field
// Bill Walker - October 2017
//------------------------------------------
global_settings {assumed_gamma 1}
#include "colors.inc"
#include "consts.inc"
light_source { <-1,8,2> color White}
camera {
 orthographic
 location <0, 0, -100>
 look_at  <0, 0,   0>
 right x*image_width
 up y*image_height
}
plane {z, 1 pigment {checker Gray20, White} scale 10}
light_source {<0, 10, -500> color White*0.5}

//----- This all macro method OK, but about 225% slower than
//      than using a single macro call to create a function.
//  BW - I get 3.184 times longer than the function-only version
#macro Spiral (X, Y)
  #declare a=1;
  #declare b=0.5;
  // calculate the target radius and theta
   #local R = sqrt (X*X +Y*Y);

    // early exit if the point requested is the origin itself
  // to avoid taking the logarithm of zero in the next step
  #if (R = 0)
   0
  #else
   #local T = atan2 (Y, X);
   // calculate the floating point approximation for n
   #local n = (log(R/a)/b - T)/(tau);

   // find the two possible radii for the closest point
   #local upper_r = a * pow(e, b * (T + tau*ceil(n)));
   #local lower_r = a * pow(e, b * (T + tau*floor(n)));

   // return the minimum distance to the target point
   min (abs(upper_r - R), abs(R - lower_r))
  #end
#end



// - Yes this a fairly straight map and it could be further optimized.
#macro DefFN0to1Val(A,B)
     #declare FNR  = function (x,y,z,X,Y) { sqrt(X*X+Y*Y) }
     #declare FNT  = function (x,y,z,X,Y) { atan2(Y,X) }
     #declare FNn  = function (x,y,z,X,Y) {
         (log(FNR(x,y,z,X,Y)/A)/B - FNT(x,y,z,X,Y))/tau
     }
     #declare FNuR = function (x,y,z,X,Y) {
         A * pow(e,B * (FNT(x,y,z,X,Y) + tau*ceil(FNn(x,y,z,X,Y))))
     }
     #declare FNlR = function (x,y,z,X,Y) {
         A * pow(e,B * (FNT(x,y,z,X,Y) + tau*floor(FNn(x,y,z,X,Y))))
     }
     #declare FNspiral = function (x,y,z,X,Y) {
         min(abs(FNuR(x,y,z,X,Y)-FNR(x,y,z,X,Y)),
             abs(FNR(x,y,z,X,Y)-FNlR(x,y,z,X,Y))
         )
     }
     #declare FN0to1Val = function (x,y,z,X,Y) {
         min(1,FNspiral(x,y,z,X,Y)/255)
     }
#end

#macro UndefAll ()
// Undefine functions so that function-defining macro can be called again
     #undef FNR
     #undef FNT
     #undef FNn
     #undef FNuR
     #undef FNlR
     #undef FNspiral
     #undef FN0to1Val
#end

//##########################################################################################
#declare Seconds = 24*60*60;


//##########################################################################################
//  Original code adapted to SDL from python source at:
//
https://swiftcoder.wordpress.com/2010/06/21/logarithmic-spiral-distance-field/
//##########################################################################################
#declare StartTime = now*Seconds;
#debug concat ( "Beginning timer. Time elapsed = ", str (StartTime-StartTime, 4,
3),  " sec. \n")
#for (i, -image_width/2, image_width/2)
 #for (j, -image_height/2, image_height/2)
  box { -0.5, 0.5 translate <i, j, 0> pigment {color rgb min(1, Spiral(i, j)/255
)} }
 #end
#end
#declare CurrentTime = now*Seconds;
#declare ElapsedTime_1 = CurrentTime-StartTime;
#debug concat ( "Original macro-in-nested-loop method. Time elapsed = ", str
(ElapsedTime_1, 4, 3),  " sec. \n")


//##########################################################################################
//  SDL using functions (defined by calling a macro ONCE) by William Pokorny:
//
http://news.povray.org/povray.general/message/%3C59da1882%40news.povray.org%3E/#%3C59da1882%40news.povray.org%3E
//##########################################################################################
#declare StartTime = now*Seconds;
#debug concat ( "Beginning timer. Time elapsed = ", str (StartTime-StartTime, 4,
3),  " sec. \n")
DefFN0to1Val(1.0,0.5)
#for (i, -image_width/2, image_width/2)
  #for (j, -image_height/2, image_height/2)
    box { -0.5,0.5 translate <i,j,0>
          pigment {color rgb FN0to1Val(0,0,0,i,j)}
        }
  #end
#end
#declare CurrentTime = now*Seconds;
#declare ElapsedTime_2 = CurrentTime-StartTime;
#debug concat ( "WP's Function-in-nested-loop method. Time elapsed = ", str
(ElapsedTime_2, 4, 3),  " sec. \n")


//##########################################################################################
//  SDL using functions (defined by calling a macro ONCE) by William Pokorny:
//
http://news.povray.org/povray.general/message/%3C59da1882%40news.povray.org%3E/#%3C59da1882%40news.povray.org%3E
//  COMMENTS PRESENT IN INNER NESTED LOOP
//  BW - I get 1.571 times longer than the function-only version
//##########################################################################################
UndefAll () // Undefine functions so that function-defining macro can be called
again in this block for accurate comparison
#declare StartTime = now*Seconds;
#debug concat ( "Beginning timer. Time elapsed = ", str (StartTime-StartTime, 4,
3),  " sec. \n")
DefFN0to1Val(1.0,0.5)
#for (i, -image_width/2, image_width/2)
  #for (j, -image_height/2, image_height/2)
    box { -0.5,0.5 translate <i,j,0>
          pigment {color rgb FN0to1Val(0,0,0,i,j)}
        }
  // Adding this comment to most nested for loop 10 times is >20% slower.
  // Adding this comment to most nested for loop 10 times is >20% slower.
  // Adding this comment to most nested for loop 10 times is >20% slower.
  // Adding this comment to most nested for loop 10 times is >20% slower.
  // Adding this comment to most nested for loop 10 times is >20% slower.
  // Adding this comment to most nested for loop 10 times is >20% slower.
  // Adding this comment to most nested for loop 10 times is >20% slower.
  // Adding this comment to most nested for loop 10 times is >20% slower.
  // Adding this comment to most nested for loop 10 times is >20% slower.
  // Adding this comment to most nested for loop 10 times is >20% slower.
  #end
#end
#declare CurrentTime = now*Seconds;
#declare ElapsedTime_3 = CurrentTime-StartTime;
#debug concat ( "WP's Function-in-nested-loop method (with comments). Time
elapsed = ", str (ElapsedTime_3, 4, 3),  " sec. \n")
#debug "\n"
#debug "\n"
#debug concat ( "   Macro-in-nested-loop method.                 Time elapsed =
", str (ElapsedTime_1, 4, 3),  " sec. ", str (ElapsedTime_1/ElapsedTime_2, 4,
3), " times slower. \n")
#debug concat ( "Function-in-nested-loop method.                 Time elapsed =
", str (ElapsedTime_2, 4, 3),  " sec. ", str (ElapsedTime_2/ElapsedTime_2, 4,
3), " [base time]. \n")
#debug concat ( "Function-in-nested-loop method (with comments). Time elapsed =
", str (ElapsedTime_3, 4, 3),  " sec. ", str (ElapsedTime_3/ElapsedTime_2, 4,
3), " times slower. \n")
#debug "\n"
#error "Aborting render phase.  Stopped after parse for time comparison of
coding methods."


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.