## Saturday, August 9, 2008

### Loops are slow in GAMS

When optimizing GAMS code it is always worthwhile to see if you can remove loops. Here is an example of an if,then,else construct:

``   1  set i /i1*i200/;   2   3  alias (i,j,k);   4  parameter a(i,j,k),b(i,j,k),c(i,j,k);   5  a(i,j,k) = uniform(0.1,1);   6  b(i,j,k) = uniform(0.1,1);   7  c(i,j,k) = uniform(0.1,1);   8   9  parameter p1(i,j,k),p2(i,j,k),p3(i,j,k);  10  11  * this is fast  12  p1(i,j,k) = ifthen(b(i,j,k)>0.5,a(i,j,k)/b(i,j,k),c(i,j,k));  13  14  * this is slow  15  loop((i,j,k),  16     if(b(i,j,k)>0.5,  17        p2(i,j,k) = a(i,j,k)/b(i,j,k)  18     else  19        p2(i,j,k) = c(i,j,k)  20     );  21  );  22  23  * this is fast but I feel uneasy about assumption that  24  * these conditions are quaranteed mutual exclusive  25  * for floating point numbers  26  p3(i,j,k) =  [a(i,j,k)/b(i,j,k)]\$(b(i,j,k)>0.5) + c(i,j,k)\$(b(i,j,k)<=0.5);``

The profiling info clearly indicates the loop is the slowest alternative:

``----      1 ExecInit                 0.000     0.000 SECS      3 Mb----      5 Assignment a             1.762     1.762 SECS    261 Mb  8000000----      6 Assignment b             1.748     3.510 SECS    518 Mb  8000000----      7 Assignment c             1.747     5.257 SECS    775 Mb  8000000----     12 Assignment p1            3.307     8.564 SECS  1,032 Mb  8000000----     15 Loop                    22.027    30.591 SECS  1,288 Mb----     26 Assignment p3            3.900    34.491 SECS  1,545 Mb  8000000``

I prefer the ifthen construct as this has a real 'else'. The assignment to p3 uses two different \$ conditions, which makes me feel uneasy.