[Mlir-commits] [mlir] f9a6d47 - Add sparse matrix multiplication integration test

Aart Bik llvmlistbot at llvm.org
Wed Jun 16 13:20:29 PDT 2021


Author: Gus Smith
Date: 2021-06-16T13:20:20-07:00
New Revision: f9a6d47c3642cb07b5e98e8b08330ccc95b85dd8

URL: https://github.com/llvm/llvm-project/commit/f9a6d47c3642cb07b5e98e8b08330ccc95b85dd8
DIFF: https://github.com/llvm/llvm-project/commit/f9a6d47c3642cb07b5e98e8b08330ccc95b85dd8.diff

LOG: Add sparse matrix multiplication integration test

Adds an integration test for the SPMM (sparse matrix multiplication) kernel, which multiplies a sparse matrix by a dense matrix, resulting in a dense matrix. This is just a simple modification on the existing matrix-vector multiplication kernel.

Reviewed By: aartbik

Differential Revision: https://reviews.llvm.org/D104334

Added: 
    mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_spmm.mlir

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_spmm.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_spmm.mlir
new file mode 100644
index 0000000000000..cadf7c4ce8e30
--- /dev/null
+++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_spmm.mlir
@@ -0,0 +1,107 @@
+// RUN: mlir-opt %s \
+// RUN:   --sparsification --sparse-tensor-conversion \
+// RUN:   --convert-linalg-to-loops --convert-vector-to-scf --convert-scf-to-std \
+// RUN:   --func-bufferize --tensor-constant-bufferize --tensor-bufferize \
+// RUN:   --std-bufferize --finalizing-bufferize  \
+// RUN:   --convert-vector-to-llvm --convert-std-to-llvm | \
+// RUN: TENSOR0="%mlir_integration_test_dir/data/wide.mtx" \
+// RUN: mlir-cpu-runner \
+// RUN:  -e entry -entry-point-result=void  \
+// RUN:  -shared-libs=%mlir_integration_test_dir/libmlir_c_runner_utils%shlibext | \
+// RUN: FileCheck %s
+
+!Filename = type !llvm.ptr<i8>
+
+#SparseMatrix = #sparse_tensor.encoding<{
+  dimLevelType = [ "dense", "compressed" ]
+}>
+
+#spmm = {
+  indexing_maps = [
+    affine_map<(i,j,k) -> (i,k)>, // A
+    affine_map<(i,j,k) -> (k,j)>, // B
+    affine_map<(i,j,k) -> (i,j)>  // X (out)
+  ],
+  iterator_types = ["parallel", "parallel", "reduction"],
+  doc = "X(i,j) += A(i,k) * B(k,j)"
+}
+
+//
+// Integration test that lowers a kernel annotated as sparse to
+// actual sparse code, initializes a matching sparse storage scheme
+// from file, and runs the resulting code with the JIT compiler.
+//
+module {
+  //
+  // A kernel that multiplies a sparse matrix A with a dense matrix B
+  // into a dense matrix X.
+  //
+  func @kernel_spmm(%arga: tensor<?x?xf64, #SparseMatrix>,
+                    %argb: tensor<?x?xf64>,
+                    %argx: tensor<?x?xf64>) -> tensor<?x?xf64> {
+    %0 = linalg.generic #spmm
+      ins(%arga, %argb: tensor<?x?xf64, #SparseMatrix>, tensor<?x?xf64>)
+      outs(%argx: tensor<?x?xf64>) {
+      ^bb(%a: f64, %b: f64, %x: f64):
+        %0 = mulf %a, %b : f64
+        %1 = addf %x, %0 : f64
+        linalg.yield %1 : f64
+    } -> tensor<?x?xf64>
+    return %0 : tensor<?x?xf64>
+  }
+
+  func private @getTensorFilename(index) -> (!Filename)
+
+  //
+  // Main driver that reads matrix from file and calls the sparse kernel.
+  //
+  func @entry() {
+    %i0 = constant 0.0 : f64
+    %c0 = constant 0 : index
+    %c1 = constant 1 : index
+    %c4 = constant 4 : index
+    %c256 = constant 256 : index
+
+    // Read the sparse matrix from file, construct sparse storage.
+    %fileName = call @getTensorFilename(%c0) : (index) -> (!Filename)
+    %a = sparse_tensor.new %fileName : !llvm.ptr<i8> to tensor<?x?xf64, #SparseMatrix>
+
+    // Initialize dense vectors.
+    %bdata = memref.alloc(%c256, %c4) : memref<?x?xf64>
+    %xdata = memref.alloc(%c4, %c4) : memref<?x?xf64>
+    scf.for %i = %c0 to %c256 step %c1 {
+      scf.for %j = %c0 to %c4 step %c1 {
+        %k0 = muli %i, %c4 : index
+        %k1 = addi %j, %k0 : index
+        %k2 = index_cast %k1 : index to i32
+        %k = sitofp %k2 : i32 to f64
+        memref.store %k, %bdata[%i, %j] : memref<?x?xf64>
+      }
+    }
+    scf.for %i = %c0 to %c4 step %c1 {
+      scf.for %j = %c0 to %c4 step %c1 {
+        memref.store %i0, %xdata[%i, %j] : memref<?x?xf64>
+      }
+    }
+    %b = memref.tensor_load %bdata : memref<?x?xf64>
+    %x = memref.tensor_load %xdata : memref<?x?xf64>
+
+    // Call kernel.
+    %0 = call @kernel_spmm(%a, %b, %x)
+      : (tensor<?x?xf64, #SparseMatrix>, tensor<?x?xf64>, tensor<?x?xf64>) -> tensor<?x?xf64>
+
+    // Print the result for verification.
+    //
+    // CHECK: ( ( 3548, 3550, 3552, 3554 ), ( 6052, 6053, 6054, 6055 ), ( -56, -63, -70, -77 ), ( -13704, -13709, -13714, -13719 ) )
+    //
+    %m = memref.buffer_cast %0 : memref<?x?xf64>
+    %v = vector.transfer_read %m[%c0, %c0], %i0: memref<?x?xf64>, vector<4x4xf64>
+    vector.print %v : vector<4x4xf64>
+
+    // Release the resources.
+    memref.dealloc %bdata : memref<?x?xf64>
+    memref.dealloc %xdata : memref<?x?xf64>
+
+    return
+  }
+}


        


More information about the Mlir-commits mailing list