Git Product home page Git Product logo

mlir-dace's Introduction

Tests

MLIR-DaCe

MLIR-DaCe is a project aiming to bridge the gap between control-centric and data-centric intermediate representations. By bridging these two groups of IRs, it allows the combination of control-centric and data-centric optimizations in optimization pipelines. In order to achieve this, MLIR-DaCe provides a data-centric dialect in MLIR to connect the MLIR and DaCe frameworks.

Building MLIR

If you have already MLIR built you can skip to Building MLIR-DaCe. Keep in mind that there are no guarantees for commits other than the one in the submodule.

First clone with submodules:

git clone --recurse-submodules https://github.com/spcl/mlir-dace
cd mlir-dace

Then build MLIR with:

cd llvm-project
mkdir build && cd build
cmake -G Ninja ../llvm -DLLVM_ENABLE_PROJECTS="mlir" -DLLVM_TARGETS_TO_BUILD="host" -DLLVM_ENABLE_ASSERTIONS=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DLLVM_ENABLE_LLD=ON -DLLVM_INSTALL_UTILS=ON

Building MLIR-DaCe

This setup assumes that you have built LLVM and MLIR in $BUILD_DIR and installed them to $PREFIX. If you built using the directions in Building MLIR, replace both with llvm-project/build/. To build and launch the tests, run

mkdir build && cd build
cmake -G Ninja .. -DMLIR_DIR=$PREFIX/lib/cmake/mlir -DLLVM_EXTERNAL_LIT=$BUILD_DIR/bin/llvm-lit
cmake --build . --target check-sdfg-opt

To build the documentation from the TableGen description of the dialect operations, run

cmake --build . --target mlir-doc

Note: Make sure to pass -DLLVM_INSTALL_UTILS=ON when building LLVM with CMake in order to install FileCheck to the chosen installation prefix.

Publication

The paper on DCIR can be found here.

If you use MLIR-DaCe, cite us:

@inproceedings{mlir-dace,
author = {Ben-Nun, Tal and Ates, Berke and Calotoiu, Alexandru and Hoefler, Torsten},
title = {Bridging Control-Centric and Data-Centric Optimization},
year = {2023},
booktitle = {Proceedings of the 21st ACM/IEEE International Symposium on Code Generation and Optimization},
series = {CGO 2023}
}

mlir-dace's People

Contributors

acalotoiu avatar berke-ates avatar tbennun avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

mlir-dace's Issues

Fail to lift scf.for to SDIR

I'm working on an example of SDDMM(sampled dense dense matrix multiplication). Namely X[i,j] = A[i,j] * sum(B[i,k] * C[k,j], k), where A is a CSR format sparse matrix. I polished the variable names in the following script.

module {
  func.func @main(%A_row: memref<?xindex>, %A_col: memref<?xindex>, %A_val: memref<?xf64>, %B: memref<?x?xf64>, %C: memref<?x?xf64>, %X: memref<?x?xf64>) -> memref<?x?xf64> {
    %c0 = arith.constant 0 : index
    %c1 = arith.constant 1 : index
    %c64 = arith.constant 64 : index
    scf.for %i = %c0 to %c64 step %c1 {
      %ptr_start = memref.load %A_row[%i] : memref<?xindex>
      %0 = arith.addi %i, %c1 : index
      %ptr_end = memref.load %A_row[%0] : memref<?xindex>
      scf.for %ptr = %ptr_start to %ptr_end step %c1 {
        %j = memref.load %A_col[%ptr] : memref<?xindex>
        %x = memref.load %X[%i, %j] : memref<?x?xf64>
        %a = memref.load %A_val[%ptr] : memref<?xf64>
        %sum = scf.for %k = %c0 to %c64 step %c1 iter_args(%accum = %x) -> (f64) {
          %b = memref.load %B[%i, %k] : memref<?x?xf64>
          %c = memref.load %C[%k, %j] : memref<?x?xf64>
          %1 = arith.mulf %b, %c : f64
          %prod = arith.mulf %a, %1 : f64
          %2 = arith.addf %accum, %prod : f64
          scf.yield %2 : f64
        }
        memref.store %sum, %X[%i, %j] : memref<?x?xf64>
      }
    }
    return %X : memref<?x?xf64>
  }
}

The error message is as follows:

: error: operand #1 does not dominate this use
          %2 = arith.addf %accum, %prod : f64
               ^
: note: see current operation: 
%0 = "sdfg.tasklet"(<<UNKNOWN SSA VALUE>>, <<UNKNOWN SSA VALUE>>) ({
^bb0(%arg0: f64, %arg1: f64):
  %0 = "arith.addf"(%arg0, %arg1) {fastmath = #arith.fastmath<none>} : (f64, f64) -> f64
  "sdfg.return"(%0) : (f64) -> ()
}) {ID = 31 : i32} : (f64, f64) -> f64
: note: operand defined here (op is neither in a parent nor in a child region)
          %prod = arith.mulf %a, %1 : f64
                  ^

This error is generated from my forked branch
https://github.com/C-TC/mlir-dace/tree/to-sdir-converter-sparse
where I added custom lifting rules for memref.dim, llvm.struct and llvm.extractvalue. But the error info remains the same after I removed these ops from script. So the error is not likely related to custom rules.

Build failures

I see 2 typical build errors following the steps in README.
1.

[u1418973@notch368:build]$ cmake --build . --target check-sdfg-opt
[1/24] Building Passes.h.inc...
FAILED: include/SDFG/Conversion/GenericToSDFG/Passes.h.inc 
...
/uufs/chpc.utah.edu/common/home//other/SANDBOX/MLIR-DACE/mlir-dace/include/SDFG/Dialect/Dialect.td:20:22: error: Value 'useFoldAPI' unknown!
    let useFoldAPI = kEmitFoldAdaptorFolder;
                     ^
[13/24] Building CXX object lib/SDFG/Utils/CMakeFiles/SDFG_UTILS.dir/OperationToString.cpp.o
FAILED: lib/SDFG/Utils/CMakeFiles/SDFG_UTILS.dir/OperationToString.cpp.o 
fatal error: SDFG/Dialect/OpsDialect.h.inc: No such file or directory
 #include "SDFG/Dialect/OpsDialect.h.inc"
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

I think I am missing something to glue before building ?
Thanks

`main-func-name` is not recognized for `--convert-to-sdfg`

In an attempt to work around #29, I tried separating I/O code (i.e. main()) and computation code (arbitrary non-main function). However I could not find a way for sdfg-opt to run over a non-main function.

Steps

I started with this example.c:

#include <stdlib.h>

int example() {
    int *A = (int *)malloc(100000 * sizeof(int));
    int *B = (int *)malloc(100000 * sizeof(int));
    for (int i = 0; i < 100000; ++i) {
        A[i] = 5;
        for (int j = 0; j < 100000; ++j)
            B[j] = A[i];
        for (int j = 0; j < 10000; ++j)
            A[j] = A[i];
    }
    int res = B[0];
    free(A);
    free(B);
    return res;
}

I compile this C into MLIR with Polygeist:

cgeist -I/usr/lib/llvm-14/lib/clang/14.0.0/include/ -S --function=example -o main.s main.c

The resulting main.s has the following content:

module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.endianness", "little">, #dlti.dl_entry<i64, dense<64> : vector<2xi32>>, #dlti.dl_entry<f80, dense<128> : vector<2xi32>>, #dlti.dl_entry<i1, dense<8> : vector<2xi32>>, #dlti.dl_entry<i8, dense<8> : vector<2xi32>>, #dlti.dl_entry<i16, dense<16> : vector<2xi32>>, #dlti.dl_entry<i32, dense<32> : vector<2xi32>>, #dlti.dl_entry<f16, dense<16> : vector<2xi32>>, #dlti.dl_entry<f64, dense<64> : vector<2xi32>>, #dlti.dl_entry<f128, dense<128> : vector<2xi32>>>, llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", llvm.target_triple = "x86_64-unknown-linux-gnu", "polygeist.target-cpu" = "x86-64", "polygeist.target-features" = "+cx8,+fxsr,+mmx,+sse,+sse2,+x87", "polygeist.tune-cpu" = "generic"} {
  func.func @example() -> i32 attributes {llvm.linkage = #llvm.linkage<external>} {
    %c10000 = arith.constant 10000 : index
    %c100000 = arith.constant 100000 : index
    %c0 = arith.constant 0 : index
    %c1 = arith.constant 1 : index
    %c5_i32 = arith.constant 5 : i32
    %alloc = memref.alloc() : memref<100000xi32>
    scf.for %arg0 = %c0 to %c100000 step %c1 {
      memref.store %c5_i32, %alloc[%arg0] : memref<100000xi32>
      scf.for %arg1 = %c0 to %c10000 step %c1 {
        %0 = memref.load %alloc[%arg0] : memref<100000xi32>
        memref.store %0, %alloc[%arg1] : memref<100000xi32>
      }
    }
    memref.dealloc %alloc : memref<100000xi32>
    return %c5_i32 : i32
  }
}

I am trying to get sdfg-opt to run over this main.s MLIR code.

Problems

1. The command line flag syntax is not immediately obvious

Note: I understand this is more an issue from MLIR's side, so I'll just leave some notes as a reference for future readers.

sdfg-opt --help shows something useful, but only partially:

  Compiler passes to run
    Passes:
      --convert-to-sdfg                                -   Convert SCF, Arith, Math and Memref dialect to SDFG dialect
        --main-func-name=<string>                      - Specify which func should be seen as the main func
      --linalg-to-sdfg                                 -   Convert Linalg dialect to SDFG dialect
      --lower-sdfg                                     -   Convert SDFG dialect to Func, CF, Memref and SCF dialects

It took me a good while to figure out that the only recognized syntax is:

sdfg-opt --convert-to-sdfg=main-func-name=example main.s

2. The main-func-name argument isn't respected

With the above command, this is all the output I get:

module {
}

I could not find any command line that would make sdfg-opt emit converted MLIR in sdfg dialect. The only way to make it work is to rename func.func @example into func.func @main.

Moreover, if the function is @main, then sdfg-opt works properly regardless of what the CLI argument value to main-func-name is (even garbage). For example:

sdfg-opt --convert-to-sdfg=main-func-name="@#$^&*" main.s

It seems like main-func-name is completely disregarded.

Utility

If main-func-name is fixed, then I can selectively run sdfg-opt through computation code while having separate facilities for handling I/O, enabling me to work around #29.

failed to legalize operation 'llvm.mlir.addressof'

I am trying to create a full C-to-DCIR optimization pipeline with llvm/Polygeist and sdfg-opt, but it doesn't look like sdfg-opt recognizes the llvm dialect, which is a fundamental requirement of C-style strings.

Reproduction steps

Use the following C source as the ultimate input:

// main.c
#include <stdio.h>
#include <stdlib.h>

static int example() {
    int *A = (int *)malloc(100000 * sizeof(int));
    int *B = (int *)malloc(100000 * sizeof(int));
    for (int i = 0; i < 100000; ++i) {
        A[i] = 5;
        for (int j = 0; j < 100000; ++j)
            B[j] = A[i];
        for (int j = 0; j < 10000; ++j)
            A[j] = A[i];
    }
    int res = B[0];
    free(A);
    free(B);
    return res;
}

int main() {
    printf("%d\n", example());
    return 0;
}

Compile into MLIR using cgeist:

cgeist -I/usr/lib/llvm-14/lib/clang/14.0.0/include/ -S -o main.s main.c

The resulting main.s file has the following content:

module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.endianness", "little">, #dlti.dl_entry<i64, dense<64> : vector<2xi32>>, #dlti.dl_entry<f80, dense<128> : vector<2xi32>>, #dlti.dl_entry<i1, dense<8> : vector<2xi32>>, #dlti.dl_entry<i8, dense<8> : vector<2xi32>>, #dlti.dl_entry<i16, dense<16> : vector<2xi32>>, #dlti.dl_entry<i32, dense<32> : vector<2xi32>>, #dlti.dl_entry<f16, dense<16> : vector<2xi32>>, #dlti.dl_entry<f64, dense<64> : vector<2xi32>>, #dlti.dl_entry<f128, dense<128> : vector<2xi32>>>, llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", llvm.target_triple = "x86_64-unknown-linux-gnu", "polygeist.target-cpu" = "x86-64", "polygeist.target-features" = "+cx8,+fxsr,+mmx,+sse,+sse2,+x87", "polygeist.tune-cpu" = "generic"} {
  llvm.mlir.global internal constant @str0("%d\0A\00") {addr_space = 0 : i32}
  llvm.func @printf(!llvm.ptr<i8>, ...) -> i32
  func.func @main() -> i32 attributes {llvm.linkage = #llvm.linkage<external>} {
    %c5_i32 = arith.constant 5 : i32
    %c1 = arith.constant 1 : index
    %c0 = arith.constant 0 : index
    %c100000 = arith.constant 100000 : index
    %c10000 = arith.constant 10000 : index
    %c0_i32 = arith.constant 0 : i32
    %0 = llvm.mlir.addressof @str0 : !llvm.ptr<array<4 x i8>>
    %1 = llvm.getelementptr %0[0, 0] : (!llvm.ptr<array<4 x i8>>) -> !llvm.ptr<i8>
    %alloc = memref.alloc() : memref<100000xi32>
    scf.for %arg0 = %c0 to %c100000 step %c1 {
      memref.store %c5_i32, %alloc[%arg0] : memref<100000xi32>
      scf.for %arg1 = %c0 to %c10000 step %c1 {
        %3 = memref.load %alloc[%arg0] : memref<100000xi32>
        memref.store %3, %alloc[%arg1] : memref<100000xi32>
      }
    }
    memref.dealloc %alloc : memref<100000xi32>
    %2 = llvm.call @printf(%1, %c5_i32) : (!llvm.ptr<i8>, i32) -> i32
    return %c0_i32 : i32
  }
}

Attempt to run sdfg-opt over main.s:

sdfg-opt --convert-to-sdfg main.s

The following error is produced:

main.s:11:10: error: failed to legalize operation 'llvm.mlir.addressof'
    %0 = llvm.mlir.addressof @str0 : !llvm.ptr<array<4 x i8>>
         ^
main.s:11:10: note: see current operation: %12 = "llvm.mlir.addressof"() {global_name = @str0} : () -> !llvm.ptr<array<4 x i8>>

As far as I understand, without recognizing the llvm dialect, it's impossible to use any C string which is often mandatory for any serialized input/output in a complete program.

Will any support be added for this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.