chapel-lang / chapel

a Productive Parallel Programming Language
https://chapel-lang.org
Other
1.79k stars 421 forks source link

[Bug]: strange behavior with generic csr/csc block-distributed arrays #26209

Open jeremiah-corrado opened 1 week ago

jeremiah-corrado commented 1 week ago

Summary of Problem

Description:

When attempting to write a procedure that can create block-distributed sparse arrays that have either a CSR or CSC layout selected by a param argument, I'm running into a strange compiler error. The following procedure should be creating a fully concrete array type which is either using csrLayout or cscLayout; however, something is going wrong with runtime type construction, where the compiler thinks that one of the underlying data structures would be generic.

Steps to Reproduce

Source Code:

use BlockDist, CompressedSparseLayout;

enum Layout { CSR, CSC }

proc makeSparseMatrix(m: int, n: int, param layout: Layout) {
    const dom = {1..m, 1..n},
          locsPerDim = sqrt(numLocales:real): int,
          grid = {0..<locsPerDim, 0..<locsPerDim},
          localeGrid = reshape(Locales[0..<grid.size], grid);

    type layoutType = if layout == Layout.CSR then csrLayout else cscLayout;
    const DenseBlkDom = dom dmapped new blockDist(boundingBox=dom,
                                                  targetLocales=localeGrid,
                                                  sparseLayoutType=layoutType);

    var SD: sparse subdomain(DenseBlkDom);
    var A: [SD] int;
    return A;
}

var sm = makeSparseMatrix(10, 10, Layout.CSR);

Error message:

The above code produces the following error message:

$CHPL_HOME/modules/internal/ChapelDomain.chpl:1621: In method 'buildArray':
$CHPL_HOME/modules/internal/ChapelDomain.chpl:1622: warning: creating an array with element type unmanaged LocSparseBlockDom(2,int(64),one,csrLayout)?
$CHPL_HOME/modules/internal/ChapelDomain.chpl:1622: error: array element type cannot currently be generic
  $CHPL_HOME/modules/internal/ChapelArray.chpl:226: called as (domain(unmanaged DefaultRectangularDom(2,int(64),one))).buildArray(type eltType = unmanaged LocSparseBlockDom(2,int(64),one,csrLayout)?, param initElts = false) from function 'chpl__buildArrayRuntimeType'
  $CHPL_HOME/modules/dists/SparseBlockDist.chpl:91: called as chpl__buildArrayRuntimeType(dom: domain(unmanaged DefaultRectangularDom(2,int(64),one)), type eltType = unmanaged LocSparseBlockDom(2,int(64),one,csrLayout)?) from initializer
  $CHPL_HOME/modules/dists/BlockDist.chpl:847: called as SparseBlockDom.init(param rank = 2, idxType: int(64), parentDom: domain(unmanaged BlockDom(2,int(64),one,csrLayout)), nnzDom: domain(unmanaged DefaultRectangularDom(1,int(64),one)), sparseLayoutType: csrLayout(?), param strides = strideKind.one, dist: unmanaged BlockImpl(2,int(64),csrLayout), whole: domain(unmanaged DefaultRectangularDom(2,int(64),one)), locDoms: <type unknown>, myLocDom: <type unknown>) from method 'dsiNewSparseDom'
  $CHPL_HOME/modules/dists/DSIUtil.chpl:783: called as (BlockImpl(2,int(64),csrLayout)).dsiNewSparseDom(param rank = 2, type idxType = int(64), dom: domain(unmanaged BlockDom(2,int(64),one,csrLayout))) from method 'newSparseDom'
  $CHPL_HOME/modules/internal/ChapelDomain.chpl:1124: called as (chpl_PrivatizedDistHelper(unmanaged BlockImpl(2,int(64),csrLayout))).newSparseDom(param rank = 2, type idxType = int(64), dom: domain(unmanaged BlockDom(2,int(64),one,csrLayout))) from initializer
  $CHPL_HOME/modules/internal/ChapelDomain.chpl:129: called as (domain(?)).init(d: blockDist(2,int(64),csrLayout), dom: domain(unmanaged BlockDom(2,int(64),one,csrLayout)), definedConst: bool) from function 'chpl__buildSparseDomainRuntimeType'
  $CHPL_HOME/modules/internal/ChapelDomain.chpl:137: called as chpl__buildSparseDomainRuntimeType(dist: blockDist(2,int(64),csrLayout), parentDom: domain(unmanaged BlockDom(2,int(64),one,csrLayout))) from function 'chpl__buildSparseDomainRuntimeTypeForParentDomain'
  asdf.chpl:16: called as chpl__buildSparseDomainRuntimeTypeForParentDomain(parentDom: domain(unmanaged BlockDom(2,int(64),one,csrLayout))) from function 'makeSparseMatrix'
  asdf.chpl:21: called as makeSparseMatrix(m: int(64), n: int(64), param layout = Layout.CSR)
note: generic instantiations are underlined in the above callstack

However, if the sparseLayoutType=layoutType argument in blockDist's initializer is hard-coded to either csrLayout or cscLayout, then the code compiles successfully. Additionally, if the whole initializer call is replaced with the following, the code will also compile successfully:

    const DenseBlkDom;
    if layout == Layout.CSR {
        DenseBlkDom = dom dmapped new blockDist(boundingBox=dom,
                                                    targetLocales=localeGrid,
                                                    sparseLayoutType=csrLayout);
    } else {
        DenseBlkDom = dom dmapped new blockDist(boundingBox=dom,
                                                    targetLocales=localeGrid,
                                                    sparseLayoutType=cscLayout);
    }

This indicates that there is something going wrong when creating a "type alias" for either csrLayout or cscLayout.

Configuration Information

printchplenv... ``` CHPL_HOST_PLATFORM: darwin CHPL_HOST_COMPILER: clang * CHPL_HOST_CC: clang CHPL_HOST_CXX: clang++ CHPL_HOST_ARCH: arm64 CHPL_TARGET_PLATFORM: darwin CHPL_TARGET_COMPILER: clang * CHPL_TARGET_CC: clang CHPL_TARGET_CXX: clang++ CHPL_TARGET_LD: /usr/bin/clang++ CHPL_TARGET_ARCH: arm64 CHPL_TARGET_CPU: unknown CHPL_LOCALE_MODEL: flat * CHPL_COMM: gasnet * CHPL_COMM_SUBSTRATE: smp * CHPL_GASNET_SEGMENT: fast CHPL_TASKS: fifo * CHPL_LAUNCHER: smp CHPL_TIMERS: generic CHPL_UNWIND: none CHPL_HOST_MEM: cstdlib * CHPL_MEM: jemalloc * CHPL_TARGET_JEMALLOC: bundled CHPL_ATOMICS: cstdlib CHPL_NETWORK_ATOMICS: none CHPL_GMP: bundled * CHPL_HWLOC: bundled * CHPL_HWLOC_PCI: enable CHPL_RE2: bundled * CHPL_LLVM: system * CHPL_LLVM_SUPPORT: system CHPL_LLVM_CONFIG: /opt/homebrew/opt/llvm@17/bin/llvm-config CHPL_LLVM_VERSION: 17 CHPL_AUX_FILESYS: none CHPL_LIB_PIC: none CHPL_SANITIZE: none CHPL_SANITIZE_EXE: none ```
bradcray commented 1 week ago

I think this might be an instance of https://github.com/chapel-lang/chapel/issues/26140. If you change this line:

    type layoutType = if layout == Layout.CSR then csrLayout else cscLayout;

to this:

    type layoutType = if layout == Layout.CSR then csrLayout() else cscLayout();

does it work?

jeremiah-corrado commented 1 week ago

yeah, that works