Search code examples
chapel

What is the best way to constrain the type of an array to be a local array with contiguous data in Chapel?


Consider the following Chapel function:

proc myfunc(arr : []?T) {}

I'd like to guarantee the array (at compile time) to be

  1. local
  2. the underlying data is stored in a contiguous memory block.

What is the best way to do this?

A possible application of this would be a case where one is calling out to a C function inside of myfunc. Doing this at compile time as a constraint might allow one to overload myfunc to take a fast path if 1 & 2 are satisfied.


Solution

  • Unfortunately, there is no official user-facing way to make such queries as of Chapel 1.22, though it would be reasonable to file feature requests on Chapel's GitHub issues page requesting such capabilities. In doing so, note that there is a subtle difference between knowing whether an array is stored in a single contiguous chunk vs. stored on a single locale vs. stored locally (e.g., an array could be stored in a single contiguous chunk yet on a locale that was distinct/remote from where the query is being made). The Chapel compiler could generally answer the first two queries statically, but the third could only be answered dynamically since it's not generally possible to reason at compile-time about the locales on which variables are stored.

    An internal / developer-oriented query that could potentially be used as a stopgap in the meantime is the .isDefaultRectangular() query which is implemented for domains and arrays and relied upon for making such queries in the implementation. It indicates whether or not the domain or array is implemented using the default domain map for rectangular domains and arrays. This domain map is, by nature, non-distributed and stored contiguously. The following example shows its behavior (TIO):

    use CyclicDist;
    
    // declare a local / non-distributed domain and array
    var Dloc = {1..3, 1..3};
    var Aloc: [Dloc] real;
    
    // declare a cyclically-distributed domain and array
    var Ddist = {1..3, 1..3} dmapped Cyclic((1,1));
    var Adist: [Ddist] real;
    
    // generic function that queries whether or not its argument uses the
    // default rectangular domain map
    proc testit(name, X) {
      writeln(name, ".isDefaultRectangular() = ", X.isDefaultRectangular());
    }
    
    // various calls to the generic function
    testit("Dloc", Dloc);
    testit("Aloc", Aloc);
    testit("Ddist", Ddist);
    testit("Adist", Adist);
    testit("slice", Aloc[2..3, 2..3]);
    

    where the output is:

    Dloc.isDefaultRectangular() = true
    Aloc.isDefaultRectangular() = true
    Ddist.isDefaultRectangular() = false
    Adist.isDefaultRectangular() = false
    slice.isDefaultRectangular() = false
    

    This query returns a param result, indicating that its results are known at compile-time. Thus, when it returns true, it's indicating that the array is stored in a single chunk on a single locale, but isn't saying whether or not it's the locale on which the query is being run. To do that, an execution time X.locale == here check would need to be used.

    Also, note that it returns false for the case of a slice of a local array. This may or may not be what you want because though the underlying array is still contiguous and local, the elements described by the slice may not necessarily be.