daphne-project / daphne-project/daphne

Improved shape inference for seq()

Open
#577 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
81
Forks
83
PR merge metrics
No merged PRs in 30d

Description

While testing the pca.daph script I noticed in the explain output that a certain seq() command introduced unknown dimensions which is something I can not explain after looking into the code.

Here's the DAPHNE command used:
``` /tmp/daphne/bin/daphne --config /tmp/daphne/UserConfig.json --select-matrix-repr --explain=property_inference scripts/algorithms/pca.daph X=\"data/wine.csv\" K=2 center=true scale=true Xout=\"./Xout.txt\" Mout=\"./Mout.txt\"```

This is the explain output. Relevant lines are ``%1, %12, %35``:
```
IR after inference:
module {
func.func @main() {
%0 = "daphne.constant"() {value = 2 : index} : () -> index
%1 = "daphne.constant"() {value = 11 : si64} : () -> si64
%2 = "daphne.constant"() {value = 1.0002042066571371 : f64} : () -> f64
%3 = "daphne.constant"() {value = false} : () -> i1
%4 = "daphne.constant"() {value = 4.897000e+03 : f64} : () -> f64
%5 = "daphne.constant"() {value = 0 : index} : () -> index
%6 = "daphne.constant"() {value = 1 : index} : () -> index
%7 = "daphne.constant"() {value = true} : () -> i1
%8 = "daphne.constant"() {value = 1.000000e+00 : f64} : () -> f64
%9 = "daphne.constant"() {value = "./Mout.txt"} : () -> !daphne.String
%10 = "daphne.constant"() {value = "./Xout.txt"} : () -> !daphne.String
%11 = "daphne.constant"() {value = -1 : si64} : () -> si64
%12 = "daphne.constant"() {value = 0.000000e+00 : f64} : () -> f64
%13 = "daphne.constant"() {value = 0x7FF8000000000000 : f64} : () -> f64
%14 = "daphne.constant"() {value = 2.000000e+00 : f64} : () -> f64
%15 = "daphne.constant"() {value = "data/wine.csv"} : () -> !daphne.String
%16 = "daphne.read"(%15) : (!daphne.String) -> !daphne.Matrix<4898x12xf64:sp[1.000000e+00]>
%17 = "daphne.meanCol"(%16) : (!daphne.Matrix<4898x12xf64:sp[1.000000e+00]>) -> !daphne.Matrix<1x12xf64>
%18 = "daphne.ewSub"(%16, %17) : (!daphne.Matrix<4898x12xf64:sp[1.000000e+00]>, !daphne.Matrix<1x12xf64>) -> !daphne.Matrix<4898x12xf64>
%19 = "daphne.ewPow"(%18, %14) : (!daphne.Matrix<4898x12xf64>, f64) -> !daphne.Matrix<4898x12xf64>
%20 = "daphne.sumCol"(%19) : (!daphne.Matrix<4898x12xf64>) -> !daphne.Matrix<1x12xf64>
%21 = "daphne.ewDiv"(%20, %4) : (!daphne.Matrix<1x12xf64>, f64) -> !daphne.Matrix<1x12xf64>
%22 = "daphne.ewSqrt"(%21) : (!daphne.Matrix<1x12xf64>) -> !daphne.Matrix<1x12xf64>
%23 = "daphne.replace"(%22, %13, %8) : (!daphne.Matrix<1x12xf64>, f64, f64) -> !daphne.Matrix<1x12xf64>
%24 = "daphne.replace"(%23, %12, %8) : (!daphne.Matrix<1x12xf64>, f64, f64) -> !daphne.Matrix<1x12xf64>
%25 = "daphne.ewDiv"(%18, %24) : (!daphne.Matrix<4898x12xf64>, !daphne.Matrix<1x12xf64>) -> !daphne.Matrix<4898x12xf64>
%26 = "daphne.meanCol"(%25) : (!daphne.Matrix<4898x12xf64>) -> !daphne.Matrix<1x12xf64>
%27 = "daphne.transpose"(%25) : (!daphne.Matrix<4898x12xf64>) -> !daphne.Matrix<12x4898xf64>
%28 = "daphne.matMul"(%27, %25, %3, %3) : (!daphne.Matrix<12x4898xf64>, !daphne.Matrix<4898x12xf64>, i1, i1) -> !daphne.Matrix<12x12xf64>
%29 = "daphne.ewDiv"(%28, %4) : (!daphne.Matrix<12x12xf64>, f64) -> !daphne.Matrix<12x12xf64>
%30 = "daphne.transpose"(%26) : (!daphne.Matrix<1x12xf64>) -> !daphne.Matrix<12x1xf64>
%31 = "daphne.matMul"(%30, %26, %3, %3) : (!daphne.Matrix<12x1xf64>, !daphne.Matrix<1x12xf64>, i1, i1) -> !daphne.Matrix<12x12xf64>
%32 = "daphne.ewMul"(%31, %2) : (!daphne.Matrix<12x12xf64>, f64) -> !daphne.Matrix<12x12xf64>
%33 = "daphne.ewSub"(%29, %32) : (!daphne.Matrix<12x12xf64>, !daphne.Matrix<12x12xf64>) -> !daphne.Matrix<12x12xf64>
%eigenValues, %eigenVectors = "daphne.eigenCal"(%33) : (!daphne.Matrix<12x12xf64>) -> (!daphne.Matrix<12x1xf64>, !daphne.Matrix<12x12xf64>)
%34 = "daphne.order"(%eigenValues, %5, %3, %7) : (!daphne.Matrix<12x1xf64>, index, i1, i1) -> !daphne.Matrix<12x1xindex>
%35 = "daphne.seq"(%12, %1, %8) : (f64, si64, f64) -> !daphne.Matrix
%36 = "daphne.cast"(%34) : (!daphne.Matrix<12x1xindex>) -> !daphne.Matrix<12x1xf64>
%37 = "daphne.ctable"(%35, %36, %8, %11, %11) : (!daphne.Matrix, !daphne.Matrix<12x1xf64>, f64, si64, si64) -> !daphne.Matrix
%38 = "daphne.matMul"(%37, %eigenValues, %3, %3) : (!daphne.Matrix, !daphne.Matrix<12x1xf64>, i1, i1) -> !daphne.Matrix
%39 = "daphne.matMul"(%eigenVectors, %37, %3, %7) : (!daphne.Matrix<12x12xf64>, !daphne.Matrix, i1, i1) -> !daphne.Matrix<12x?xf64>
%40 = "daphne.sliceRow"(%38, %5, %0) : (!daphne.Matrix, index, index) -> !daphne.Matrix
%41 = "daphne.sliceCol"(%40, %5, %6) : (!daphne.Matrix, index, index) -> !daphne.Matrix
%42 = "daphne.sliceCol"(%39, %5, %0) : (!daphne.Matrix<12x?xf64>, index, index) -> !daphne.Matrix<12x?xf64>
%43 = "daphne.matMul"(%25, %42, %3, %3) : (!daphne.Matrix<4898x12xf64>, !daphne.Matrix<12x?xf64>, i1, i1) -> !daphne.Matrix<4898x?xf64>
"daphne.write"(%43, %10) : (!daphne.Matrix<4898x?xf64>, !daphne.String) -> ()
"daphne.write"(%42, %9) : (!daphne.Matrix<12x?xf64>, !daphne.String) -> ()
"daphne.return"() : () -> ()
}
}
```

Here is the PCA algorithm reduced to the relevant parts:
```
... // line 41:
X = readMatrix($X);
... // line 46:
M = as.si64(ncol(X));
... // line 78:
diagmat = ctable(seq(0.0, M - 1, 1.0), as.f64(decreasing_Idx));
...
```

Relevant code from DaphneInferShapeOpInterface.cpp:
``` cpp
// line 133:
ssize_t daphne::SeqOp::inferNumRows() {
Type fromTy = getFrom().getType();
if(fromTy.isF64()) {
try {
double vFrom = CompilerUtils::constantOrThrow(getFrom());
double vTo = CompilerUtils::constantOrThrow(getTo());
double vInc = CompilerUtils::constantOrThrow(getInc());
return floor(vTo / vInc - vFrom / vInc) + 1;
}
catch(const std::runtime_error & e) {
return -1;
}
}
...
```

It remains a mystery to me why, even though it is a constant in the explain output, the evaluation of ``double vTo = ...`` in the ``inferNumRows()`` method is not found to be const even after the three (I even added a fourth one just to test) invocations of the shape inference pass.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.