diff --git a/modules/internal/ChapelArray.chpl b/modules/internal/ChapelArray.chpl index 8807f19363e3..de92afd08dec 100644 --- a/modules/internal/ChapelArray.chpl +++ b/modules/internal/ChapelArray.chpl @@ -3010,11 +3010,48 @@ module ChapelArray { return b; } + // + // These control an optimization in which copying an array from one + // locale to another will also copy the array's domain if we believe + // it's safe to do so. This optimization is currently off by + // default because it was completed close to Chapel 2.1 and we + // wanted more time to live with it before having it on by default. + // + config param localizeConstDomains = false, + debugLocalizedConstDomains = false; + pragma "init copy fn" proc chpl__initCopy(const ref rhs: [], definedConst: bool) { - pragma "no copy" - var lhs = chpl__coerceCopy(rhs.type, rhs, definedConst); - return lhs; + // + // create a local copy of a remote array's domain if... + // - the optimization is enabled + // - we're running using multiple locales + // - the array copy we're declaring is 'const' (implying that + // its domain can't be re-assigned while it's alive) or the + // original domain is 'const' (implying that it can never + // be re-assigned) + // - the domain is on a remote locale + // + const localize = (localizeConstDomains && + numLocales > 1 && + (definedConst || rhs.domain.definedConst) && + rhs.domain._value.locale != here); + if debugLocalizedConstDomains then + writeln("In initCopy(definedConst=", definedConst, + "), domain definedConst: ", rhs.domain.definedConst, "; ", + if localize then "localizing" else "taking normal path"); + if localize { + // localize domain for efficiency since it's OK to do so + const lhsDom = rhs.domain; + pragma "no copy" + var lhs: [lhsDom] rhs.eltType = rhs; + return lhs; + } else { + // otherwise, do what we traditionally have done + pragma "no copy" + var lhs = chpl__coerceCopy(rhs.type, rhs, definedConst); + return lhs; + } } // TODO: why is the compiler calling chpl__autoCopy on an array at all? diff --git a/test/arrays/localizeConstDom.chpl b/test/arrays/localizeConstDom.chpl new file mode 100644 index 000000000000..5e7fd585bcfa --- /dev/null +++ b/test/arrays/localizeConstDom.chpl @@ -0,0 +1,71 @@ +writeln("all var"); +{ + var A: [1..10] real; + writeln("After A"); + var B = A; + writeln("After B"); + var C: [1..10] real = A; + writeln("After C"); + on Locales[numLocales-1] { + var D = A; + writeln("After D"); + local { + var sz = D.size; + } + } +} +writeln(); + +writeln("const A, var others"); +{ + const A: [1..10] real; + writeln("After A"); + var B = A; + writeln("After B"); + var C: [1..10] real = A; + writeln("After C"); + on Locales[numLocales-1] { + var D = A; + writeln("After D"); + local { + var sz = D.size; + } + } +} +writeln(); + +writeln("var A, const others"); +{ + var A: [1..10] real; + writeln("After A"); + const B = A; + writeln("After B"); + const C: [1..10] real = A; + writeln("After C"); + on Locales[numLocales-1] { + const D = A; + writeln("After D"); + local { + var sz = D.size; + } + } +} +writeln(); + +writeln("var Dom, var A, const others"); +{ + var Dom = {1..10}; + var A: [Dom] real; + writeln("After A"); + const B = A; + writeln("After B"); + const C: [1..10] real = A; + writeln("After C"); + on Locales[numLocales-1] { + const D = A; + writeln("After D"); + local { + var sz = D.size; + } + } +} diff --git a/test/arrays/localizeConstDom.comm-none.good b/test/arrays/localizeConstDom.comm-none.good new file mode 100644 index 000000000000..516f0ae380bb --- /dev/null +++ b/test/arrays/localizeConstDom.comm-none.good @@ -0,0 +1,31 @@ +all var +After A +In initCopy(definedConst=false), domain definedConst: true; taking normal path +After B +After C +In initCopy(definedConst=false), domain definedConst: true; taking normal path +After D + +const A, var others +After A +In initCopy(definedConst=false), domain definedConst: true; taking normal path +After B +After C +In initCopy(definedConst=false), domain definedConst: true; taking normal path +After D + +var A, const others +After A +In initCopy(definedConst=true), domain definedConst: true; taking normal path +After B +After C +In initCopy(definedConst=true), domain definedConst: true; taking normal path +After D + +var Dom, var A, const others +After A +In initCopy(definedConst=true), domain definedConst: false; taking normal path +After B +After C +In initCopy(definedConst=true), domain definedConst: false; taking normal path +After D diff --git a/test/arrays/localizeConstDom.compopts b/test/arrays/localizeConstDom.compopts new file mode 100644 index 000000000000..d542e4374a27 --- /dev/null +++ b/test/arrays/localizeConstDom.compopts @@ -0,0 +1 @@ +-slocalizeConstDomains=true -sdebugLocalizedConstDomains=true diff --git a/test/arrays/localizeConstDom.good b/test/arrays/localizeConstDom.good new file mode 100644 index 000000000000..9e3b2c9996ad --- /dev/null +++ b/test/arrays/localizeConstDom.good @@ -0,0 +1,31 @@ +all var +After A +In initCopy(definedConst=false), domain definedConst: true; taking normal path +After B +After C +In initCopy(definedConst=false), domain definedConst: true; localizing +After D + +const A, var others +After A +In initCopy(definedConst=false), domain definedConst: true; taking normal path +After B +After C +In initCopy(definedConst=false), domain definedConst: true; localizing +After D + +var A, const others +After A +In initCopy(definedConst=true), domain definedConst: true; taking normal path +After B +After C +In initCopy(definedConst=true), domain definedConst: true; localizing +After D + +var Dom, var A, const others +After A +In initCopy(definedConst=true), domain definedConst: false; taking normal path +After B +After C +In initCopy(definedConst=true), domain definedConst: false; localizing +After D diff --git a/test/arrays/localizeConstDom.numlocales b/test/arrays/localizeConstDom.numlocales new file mode 100644 index 000000000000..0cfbf08886fc --- /dev/null +++ b/test/arrays/localizeConstDom.numlocales @@ -0,0 +1 @@ +2 diff --git a/test/distributions/block/checkLocalizeConstBlockDom.chpl b/test/distributions/block/checkLocalizeConstBlockDom.chpl new file mode 100644 index 000000000000..357563ef7a83 --- /dev/null +++ b/test/distributions/block/checkLocalizeConstBlockDom.chpl @@ -0,0 +1,12 @@ +use BlockDist; + +const D = {1..10} dmapped new blockDist({1..100}); + +var A: [D] real; + +on Locales[numLocales-1] { + // This should not cause the localization optimization to fire since + // 'A' is distributed + var B = A; + writeln(B); +} diff --git a/test/distributions/block/checkLocalizeConstBlockDom.compopts b/test/distributions/block/checkLocalizeConstBlockDom.compopts new file mode 100644 index 000000000000..d542e4374a27 --- /dev/null +++ b/test/distributions/block/checkLocalizeConstBlockDom.compopts @@ -0,0 +1 @@ +-slocalizeConstDomains=true -sdebugLocalizedConstDomains=true diff --git a/test/distributions/block/checkLocalizeConstBlockDom.good b/test/distributions/block/checkLocalizeConstBlockDom.good new file mode 100644 index 000000000000..73d505adf264 --- /dev/null +++ b/test/distributions/block/checkLocalizeConstBlockDom.good @@ -0,0 +1,5 @@ +In initCopy(definedConst=false), domain definedConst: false; taking normal path +In initCopy(definedConst=false), domain definedConst: false; taking normal path +In initCopy(definedConst=false), domain definedConst: true; taking normal path +In initCopy(definedConst=false), domain definedConst: false; taking normal path +0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 diff --git a/test/multilocale/diten/localBlock/needMultiLocales/localBlock5-localize.good b/test/multilocale/diten/localBlock/needMultiLocales/localBlock5-localize.good new file mode 100644 index 000000000000..5190b6e7b701 --- /dev/null +++ b/test/multilocale/diten/localBlock/needMultiLocales/localBlock5-localize.good @@ -0,0 +1 @@ +{a = -2, next = {a = 2, next = {a = 3, next = nil}}} {a = -1, next = {a = 3, next = {a = 4, next = nil}}} {a = 0, next = {a = 4, next = {a = 5, next = nil}}} {a = 1, next = {a = 5, next = {a = 6, next = nil}}} {a = 2, next = {a = 6, next = {a = 7, next = nil}}} diff --git a/test/multilocale/diten/localBlock/needMultiLocales/localBlock5.compopts b/test/multilocale/diten/localBlock/needMultiLocales/localBlock5.compopts new file mode 100644 index 000000000000..4a9b709d25ce --- /dev/null +++ b/test/multilocale/diten/localBlock/needMultiLocales/localBlock5.compopts @@ -0,0 +1,2 @@ +-slocalizeConstDomains=false +-slocalizeConstDomains=true # localBlock5-localize.good