Skip to content

Commit

Permalink
Avoid creating an array in chpl__sumType()
Browse files Browse the repository at this point in the history
chpl__sumType() computes the type of `x+x` given the type of `x`.
To do so, it declares the variable `x`, computes `x+x` and takes its type.
All this happens strictly at compile time, which is desired, as long as
the type is not a "runtime type" i.e. an array or a domain.

This is time-consuming in the case `x` is an array. Even though chpl__sumType()
is smart to run `x+x` only on a variable of the array's element type, and
if that itself is an array, then only on its element type recursively,
allocating an array is already expensive, especially when:
* an array is large,
* it is an array of arrays, and/or
* it is a distributed array.

This is one of the causes of the slowdown discussed in chapel-lang#11333.

In most practical cases, the type of `x+x` is the same as the type of `x`.
If so, we can save the hassle of allocating the array.

This PR adds a check "is the type of `x+x` the same as the type of `x` ?".
If so, chpl__sumType() skips declaring the variable `x`, instead returning
its type immediately.

This check is "conservative" aka has false negatives. I.e. it may say "no"
in some cases where chpl__sumType() could return immediately. If so,
chpl__sumType() will do the unnecessary work of allocating the `x`.
This is largly only a performance concern - because chpl__sumType()
still produces a correct result. In practice this situation should be rare.

While there, emit user-friendly error when + reducing something that does not
have a valid + implementation.
  • Loading branch information
vasslitvinov committed Nov 2, 2018
1 parent 6252fda commit 8c0f6ab
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 0 deletions.
44 changes: 44 additions & 0 deletions modules/internal/ChapelReduce.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,45 @@ module ChapelReduce {
delete localOp;
}

// Return true for simple cases where x.type == (x+x).type.
// This should be true for the great majority of cases in practice.
// This proc helps us avoid run-time computations upon chpl__sumType().
// Which is important for costly cases ex. when 'eltType' is an array.
// It also allows us to accept 'eltType' that is the result of
// __primitive("static typeof"), i.e. with uninitialized _RuntimeTypeInfo.
//
proc chpl_sumTypeIsSame(type eltType) param {
if isNumeric(eltType) || isString(eltType) {
return true;

} else if isDomain(eltType) {
// Since it is a param function, this code will be squashed.
// It will not execute at run time.
var d: eltType;
// + preserves the type for associative domains.
// Todo: any other easy-to-compute cases?
return isAssociativeDom(d);

} else if isArray(eltType) {
// Follow the lead of chpl_buildStandInRTT. Thankfully, this code
// will not execute at run time. Otherwise we could get in trouble,
// as "static typeof" produces uninitialized _RuntimeTypeInfo values.
type arrInstType = __primitive("static field type", eltType, "_instance");
var instanceObj: arrInstType;
type instanceEltType = __primitive("static typeof", instanceObj.eltType);
return chpl_sumTypeIsSame(instanceEltType);

} else {
// Otherwise, let chpl__sumType() deal with it.
return false;
}
}

proc chpl__sumType(type eltType) type {
if chpl_sumTypeIsSame(eltType) {
return eltType;
} else {
// The answer may or may not be 'eltType'.
var x: eltType;
if isArray(x) {
type xET = x.eltType;
Expand All @@ -61,8 +99,14 @@ module ChapelReduce {
else
return [x.domain] xST;
} else {
use Reflection;
if ! canResolve("+", x, x) then
// Issue a user-friendly error.
compilerError("+ reduce cannot be used on values of the type ",
eltType:string);
return (x + x).type;
}
}
}

pragma "ReduceScanOp"
Expand Down
9 changes: 9 additions & 0 deletions test/reductions/vass/illegal-elttype.chpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

record RRR { }

var AAA: [1..100] RRR;

proc main {
var result = + reduce AAA;
writeln(result);
}
2 changes: 2 additions & 0 deletions test/reductions/vass/illegal-elttype.good
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
illegal-elttype.chpl:6: In function 'main':
illegal-elttype.chpl:7: error: + reduce cannot be used on values of the type RRR

0 comments on commit 8c0f6ab

Please sign in to comment.