Use `param` to choose algorithm

Suppose that I have 2 algorithms to implement a function and I would like to allow the user to choose which one to use. One way I would approach the problem would be to use config param, i.e. I would do something like the following

config param fastAlg = false;

proc f() {
  if fastAlg then writeln("fast algorithm");
  else writeln("slow algorithm");
}

f();

this produces

lferrant@LAPTOP-HGM2FD2S:~$ chpl tmp.chpl
lferrant@LAPTOP-HGM2FD2S:~$ ./tmp
slow algorithm
lferrant@LAPTOP-HGM2FD2S:~$ chpl tmp.chpl -s fastAlg=true
lferrant@LAPTOP-HGM2FD2S:~$ ./tmp
fast algorithm

which seems to achieve what I was after. My question is, is this the right way of doing it? Do I understand correctly, that those if statements will be resolved already at compile time?

Alternatively, I would probably create a class for each algorithm, define a method solve (or whatever) for each of those and then do something like

proc solve(input1, input2, method=new Alg1()) {
  return method.solve(input1, input2);
}

probably with a where clause to restrict what method can be. Comments whether this could be a good approach in Chapel? I guess the second approach can be handier if the algorithms has itself some parameters (max iterations, tolerance, etc.) then those can be encapsulated inside the algorithm object.

Hello Luca,

Your initial way of branching based on a param flag is a good way of achieving what you want. Similarly, for more advanced applications, you might want to consider a class/record-based approach, but that wouldn't be the first thing that I'd do myself, it feels like too much code if it is just to choose a different code path.

For the if based approach, note that a very similar approach is to have two functions with where clauses checking for your param flag. The differences from compilation and execution performance standpoint would probably be too subtle. Which one is better style? It is probably more of a personal taste than anything else. For choosing two algorithms that are doing the same thing, I would (again, personally, not as a rule or even convention) probably write helpers with different names and have the main "user-facing" function call the correct one based on the flag. Something like:

config param doFooFast = false;

// This has 0 execution time cost because of inlining and
// the param branch
inline proc foo() {
  if doFooFast then
    fancyAlgorithm();
  else
    mehAlgorithm();
}

// `private` is only applicable for module-scope functions
private proc fancyAlgorithm() {}
private proc mehAlgorithm() {}

I like this style because it is quite self-documenting. If you inline the algorithms in branches, or have two functions with where clauses, you'd probably add a comment what those algorithms are. This way the algorithm names can be in the code itself, for example.

Engin

2 Likes

Thanks for the reply! To make sure I understand, the approach with where clauses would be something like the following?

config param doFooFast = false;

proc foo() where doFooFast {
    // fancyAlgorithm code here
}

proc foo() where doFooFast == false {
    // mehAlgorithm code here
}

I guess it depends on how self-documenting the names foo and doFooFast are, but in general I'd agree your solution with helper functions and inlined external function is more readable, I'll probably go with that.

The record/class approach might be handier for much more complex scenarios, where algorithms have different parameters and maybe you want to cache some computations (e.g. ODE solver toolkit, one record for each solver), but for simple cases is indeed an overkill.

1 Like

All that sounds right to me.

An irrelevant nit is that you'd probably want where !doFooFast, instead of comparing a bool to false (Or compare it to true above). But that is also a matter of style.

1 Like