[Mlir-commits] [mlir] 412d784 - [mlir][sparse][CRunnerUtils] Add shuffle in CRunnerUtils (#77124)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Tue Jan 9 16:46:39 PST 2024
Author: Yinying Li
Date: 2024-01-09T19:46:35-05:00
New Revision: 412d784188257f6b8a3748ac9a800002db861181
URL: https://github.com/llvm/llvm-project/commit/412d784188257f6b8a3748ac9a800002db861181
DIFF: https://github.com/llvm/llvm-project/commit/412d784188257f6b8a3748ac9a800002db861181.diff
LOG: [mlir][sparse][CRunnerUtils] Add shuffle in CRunnerUtils (#77124)
Shuffle can generate an array of unique and random numbers from 0 to
size-1. It can be used to generate tensors with specified sparsity
level.
Added:
mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir
Modified:
mlir/include/mlir/ExecutionEngine/CRunnerUtils.h
mlir/lib/ExecutionEngine/CRunnerUtils.cpp
Removed:
################################################################################
diff --git a/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h b/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h
index 76b04145b482e4..812f719e723eb3 100644
--- a/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h
+++ b/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h
@@ -482,10 +482,16 @@ extern "C" MLIR_CRUNNERUTILS_EXPORT double rtclock();
//===----------------------------------------------------------------------===//
// Uses a seed to initialize a random generator and returns the generator.
extern "C" MLIR_CRUNNERUTILS_EXPORT void *rtsrand(uint64_t s);
-// Returns a random number in the range of [0, m).
-extern "C" MLIR_CRUNNERUTILS_EXPORT uint64_t rtrand(void *, uint64_t m);
+// Uses a random number generator g and returns a random number
+// in the range of [0, m).
+extern "C" MLIR_CRUNNERUTILS_EXPORT uint64_t rtrand(void *g, uint64_t m);
// Deletes the random number generator.
-extern "C" MLIR_CRUNNERUTILS_EXPORT void rtdrand(void *);
+extern "C" MLIR_CRUNNERUTILS_EXPORT void rtdrand(void *g);
+// Uses a random number generator g and std::shuffle to modify mref
+// in place. Memref mref will be a permutation of all numbers
+// in the range of [0, size of mref).
+extern "C" MLIR_CRUNNERUTILS_EXPORT void
+_mlir_ciface_shuffle(StridedMemRefType<uint64_t, 1> *mref, void *g);
//===----------------------------------------------------------------------===//
// Runtime support library to allow the use of std::sort in MLIR program.
diff --git a/mlir/lib/ExecutionEngine/CRunnerUtils.cpp b/mlir/lib/ExecutionEngine/CRunnerUtils.cpp
index e28e75eb110303..48e4b8cd88b58e 100644
--- a/mlir/lib/ExecutionEngine/CRunnerUtils.cpp
+++ b/mlir/lib/ExecutionEngine/CRunnerUtils.cpp
@@ -31,6 +31,7 @@
#include <cinttypes>
#include <cstdio>
#include <cstdlib>
+#include <numeric>
#include <random>
#include <string.h>
@@ -176,6 +177,17 @@ extern "C" void rtdrand(void *g) {
delete generator;
}
+extern "C" void _mlir_ciface_shuffle(StridedMemRefType<uint64_t, 1> *mref,
+ void *g) {
+ assert(mref);
+ assert(mref->strides[0] == 1); // consecutive
+ std::mt19937 *generator = static_cast<std::mt19937 *>(g);
+ uint64_t s = mref->sizes[0];
+ uint64_t *data = mref->data + mref->offset;
+ std::iota(data, data + s, 0);
+ std::shuffle(data, data + s, *generator);
+}
+
#define IMPL_STDSORT(VNAME, V) \
extern "C" void _mlir_ciface_stdSort##VNAME(uint64_t n, \
StridedMemRefType<V, 1> *vref) { \
diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir
new file mode 100644
index 00000000000000..fcc16f5e9cb4f6
--- /dev/null
+++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir
@@ -0,0 +1,95 @@
+//--------------------------------------------------------------------------------------------------
+// WHEN CREATING A NEW TEST, PLEASE JUST COPY & PASTE WITHOUT EDITS.
+//
+// Set-up that's shared across all tests in this directory. In principle, this
+// config could be moved to lit.local.cfg. However, there are downstream users that
+// do not use these LIT config files. Hence why this is kept inline.
+//
+// DEFINE: %{sparsifier_opts} = enable-runtime-library=true
+// DEFINE: %{sparsifier_opts_sve} = enable-arm-sve=true %{sparsifier_opts}
+// DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}"
+// DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}"
+// DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils
+// DEFINE: %{run_opts} = -e entry -entry-point-result=void
+// DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs}
+// DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs}
+//
+// DEFINE: %{env} =
+//--------------------------------------------------------------------------------------------------
+
+// RUN: %{compile} | %{run} | FileCheck %s
+
+//
+// Integration test that generates a tensor with specified sparsity level.
+//
+
+!Generator = !llvm.ptr
+!Array = !llvm.ptr
+
+#SparseVector = #sparse_tensor.encoding<{
+ map = (d0) -> (d0 : compressed)
+}>
+
+module {
+ func.func private @rtsrand(index) -> (!Generator)
+ func.func private @rtrand(!Generator, index) -> (index)
+ func.func private @rtdrand(!Generator) -> ()
+ func.func private @shuffle(memref<?xi64>, !Generator) -> () attributes { llvm.emit_c_interface }
+
+ //
+ // Main driver.
+ //
+ func.func @entry() {
+ %c0 = arith.constant 0 : index
+ %c1 = arith.constant 1 : index
+ %f0 = arith.constant 0.0 : f64
+ %c99 = arith.constant 99 : index
+ %c100 = arith.constant 100 : index
+
+ // Set up input size and sparsity level.
+ %size = arith.constant 50 : index
+ %sparsity = arith.constant 90 : index
+ %zeros = arith.muli %size, %sparsity : index
+ %nz = arith.floordivsi %zeros, %c100 : index
+ %nse = arith.subi %size, %nz : index
+
+ // Set up an empty vector.
+ %empty = tensor.empty(%size) : tensor<?xf64>
+ %zero_vec = linalg.fill ins(%f0 : f64) outs(%empty : tensor<?xf64>) -> tensor<?xf64>
+
+ // Generate shuffled indices in the range of [0, %size).
+ %array = memref.alloc (%size) : memref<?xi64>
+ %g = func.call @rtsrand(%c0) : (index) ->(!Generator)
+ func.call @shuffle(%array, %g) : (memref<?xi64>, !Generator) -> ()
+
+ // Iterate through the number of nse indices to insert values.
+ %output = scf.for %iv = %c0 to %nse step %c1 iter_args(%iter = %zero_vec) -> tensor<?xf64> {
+ // Fetch the index to insert value from shuffled index array.
+ %val = memref.load %array[%iv] : memref<?xi64>
+ %idx = arith.index_cast %val : i64 to index
+ // Generate a random number from 1 to 100.
+ %ri0 = func.call @rtrand(%g, %c99) : (!Generator, index) -> (index)
+ %ri1 = arith.addi %ri0, %c1 : index
+ %r0 = arith.index_cast %ri1 : index to i64
+ %fr = arith.uitofp %r0 : i64 to f64
+ // Insert the random number to current index.
+ %out = tensor.insert %fr into %iter[%idx] : tensor<?xf64>
+ scf.yield %out : tensor<?xf64>
+ }
+
+ %sv = sparse_tensor.convert %output : tensor<?xf64> to tensor<?xf64, #SparseVector>
+ %n0 = sparse_tensor.number_of_entries %sv : tensor<?xf64, #SparseVector>
+
+ // Print the number of non-zeros for verification.
+ //
+ // CHECK: 5
+ vector.print %n0 : index
+
+ // Release the resources.
+ bufferization.dealloc_tensor %sv : tensor<?xf64, #SparseVector>
+ memref.dealloc %array : memref<?xi64>
+ func.call @rtdrand(%g) : (!Generator) -> ()
+
+ return
+ }
+}
More information about the Mlir-commits
mailing list