daphne-project / daphne-project/daphne
Improved shape inference for seq()
- 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
Assessment
This issue has not been assessed yet.