https://github.com/yinying-lisa-li updated https://github.com/llvm/llvm-project/pull/77124
>From 1c774e6c6ae3c5c7be9291677651d20c8979c7f5 Mon Sep 17 00:00:00 2001 From: Yinying Li <yinyin...@google.com> Date: Fri, 5 Jan 2024 01:17:39 +0000 Subject: [PATCH 1/6] [mlir][sparse][CRunnerUtils] Add shuffle and shuffleFree in CRunnerUtils to generate unique and random numbers It's helpful for generating tensor with specified sparsity level. --- .../mlir/ExecutionEngine/CRunnerUtils.h | 4 + mlir/lib/ExecutionEngine/CRunnerUtils.cpp | 16 +++ .../SparseTensor/CPU/sparse_generate.mlir | 108 ++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir diff --git a/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h b/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h index 76b04145b482e4..747e5ca40ca6f6 100644 --- a/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h +++ b/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h @@ -486,6 +486,10 @@ extern "C" MLIR_CRUNNERUTILS_EXPORT void *rtsrand(uint64_t s); extern "C" MLIR_CRUNNERUTILS_EXPORT uint64_t rtrand(void *, uint64_t m); // Deletes the random number generator. extern "C" MLIR_CRUNNERUTILS_EXPORT void rtdrand(void *); +// Returns a pointer to an array of random numbers in the range of [0, s). +extern "C" MLIR_CRUNNERUTILS_EXPORT void *shuffle(uint64_t s, void *g); +// Deletes the array of random numbers. +extern "C" MLIR_CRUNNERUTILS_EXPORT void shuffleFree(void *a); //===----------------------------------------------------------------------===// // 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..3a3261d1ad4e03 100644 --- a/mlir/lib/ExecutionEngine/CRunnerUtils.cpp +++ b/mlir/lib/ExecutionEngine/CRunnerUtils.cpp @@ -160,6 +160,22 @@ extern "C" void mlirAlignedFree(void *ptr) { #endif } +/// Generates an array with unique and random numbers from 0 to s-1. +extern "C" void *shuffle(uint64_t s, void *g) { + std::mt19937 *generator = static_cast<std::mt19937 *>(g); + uint64_t *output = new uint64_t[s]; + std::vector<uint64_t> arr(s); + std::iota(arr.begin(), arr.end(), 0); + std::shuffle(arr.begin(), arr.end(), *generator); + std::copy(arr.begin(), arr.end(), output); + return output; +} + +extern "C" void shuffleFree(void *a) { + uint64_t *arr = static_cast<uint64_t *>(a); + delete[] arr; +} + extern "C" void *rtsrand(uint64_t s) { // Standard mersenne_twister_engine seeded with s. return new std::mt19937(s); 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..250993d874b370 --- /dev/null +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir @@ -0,0 +1,108 @@ +//-------------------------------------------------------------------------------------------------- +// 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 +// +// Do the same run, but now with direct IR generation. +// REDEFINE: %{sparsifier_opts} = enable-runtime-library=false +// RUN: %{compile} | %{run} | FileCheck %s +// +// Do the same run, but now with direct IR generation and vectorization. +// REDEFINE: %{sparsifier_opts} = enable-runtime-library=false vl=2 reassociate-fp-reductions=true enable-index-optimizations=true +// RUN: %{compile} | %{run} | FileCheck %s +// +// Do the same run, but now with direct IR generation and VLA vectorization. +// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | %{run_sve} | 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(index, !Generator) -> (!Array) + func.func private @shuffleFree(!Array) -> () + + // + // 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). + %g = func.call @rtsrand(%c0) : (index) ->(!Generator) + %res = func.call @shuffle(%size, %g) : (index, !Generator) -> !Array + + // 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. + %r = arith.index_cast %iv : index to i64 + %arr = llvm.getelementptr %res[%r] : (!llvm.ptr, i64) -> !llvm.ptr, i64 + %val = llvm.load %arr : !Array -> i64 + %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> + func.call @shuffleFree(%res) : (!Array) -> () + func.call @rtdrand(%g) : (!Generator) -> () + + return + } +} \ No newline at end of file >From bebf352d4d5c9b85c59e8f61e46198575cc5276d Mon Sep 17 00:00:00 2001 From: Yinying Li <yinyin...@google.com> Date: Sun, 7 Jan 2024 21:47:47 +0000 Subject: [PATCH 2/6] address comments and use memref instead of pointer --- .../mlir/ExecutionEngine/CRunnerUtils.h | 13 +++++----- mlir/lib/ExecutionEngine/CRunnerUtils.cpp | 25 +++++++------------ .../SparseTensor/CPU/sparse_generate.mlir | 25 +++++-------------- 3 files changed, 21 insertions(+), 42 deletions(-) diff --git a/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h b/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h index 747e5ca40ca6f6..eeb300935dc865 100644 --- a/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h +++ b/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h @@ -482,14 +482,13 @@ 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 *); -// Returns a pointer to an array of random numbers in the range of [0, s). -extern "C" MLIR_CRUNNERUTILS_EXPORT void *shuffle(uint64_t s, void *g); -// Deletes the array of random numbers. -extern "C" MLIR_CRUNNERUTILS_EXPORT void shuffleFree(void *a); +extern "C" MLIR_CRUNNERUTILS_EXPORT void rtdrand(void *g); +// Uses a random number generator g and std::shuffle to modify memref m in place. +// m will be populated with unique and random numbers in the range of [0, size of m). +extern "C" MLIR_CRUNNERUTILS_EXPORT void _mlir_ciface_shuffle(StridedMemRefType<uint64_t, 1> *m, 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 3a3261d1ad4e03..7949e759e7b36a 100644 --- a/mlir/lib/ExecutionEngine/CRunnerUtils.cpp +++ b/mlir/lib/ExecutionEngine/CRunnerUtils.cpp @@ -160,22 +160,6 @@ extern "C" void mlirAlignedFree(void *ptr) { #endif } -/// Generates an array with unique and random numbers from 0 to s-1. -extern "C" void *shuffle(uint64_t s, void *g) { - std::mt19937 *generator = static_cast<std::mt19937 *>(g); - uint64_t *output = new uint64_t[s]; - std::vector<uint64_t> arr(s); - std::iota(arr.begin(), arr.end(), 0); - std::shuffle(arr.begin(), arr.end(), *generator); - std::copy(arr.begin(), arr.end(), output); - return output; -} - -extern "C" void shuffleFree(void *a) { - uint64_t *arr = static_cast<uint64_t *>(a); - delete[] arr; -} - extern "C" void *rtsrand(uint64_t s) { // Standard mersenne_twister_engine seeded with s. return new std::mt19937(s); @@ -192,6 +176,15 @@ extern "C" void rtdrand(void *g) { delete generator; } +extern "C" void _mlir_ciface_shuffle(StridedMemRefType<uint64_t, 1> *m, void *g) { + std::mt19937 *generator = static_cast<std::mt19937 *>(g); + uint64_t s = m->sizes[0]; + std::vector<uint64_t> arr(s); + std::iota(arr.begin(), arr.end(), 0); + std::shuffle(arr.begin(), arr.end(), *generator); + std::copy(arr.begin(), arr.end(), m->data); +} + #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 index 250993d874b370..fcc16f5e9cb4f6 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir @@ -18,17 +18,6 @@ //-------------------------------------------------------------------------------------------------- // RUN: %{compile} | %{run} | FileCheck %s -// -// Do the same run, but now with direct IR generation. -// REDEFINE: %{sparsifier_opts} = enable-runtime-library=false -// RUN: %{compile} | %{run} | FileCheck %s -// -// Do the same run, but now with direct IR generation and vectorization. -// REDEFINE: %{sparsifier_opts} = enable-runtime-library=false vl=2 reassociate-fp-reductions=true enable-index-optimizations=true -// RUN: %{compile} | %{run} | FileCheck %s -// -// Do the same run, but now with direct IR generation and VLA vectorization. -// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | %{run_sve} | FileCheck %s %} // // Integration test that generates a tensor with specified sparsity level. @@ -45,8 +34,7 @@ module { func.func private @rtsrand(index) -> (!Generator) func.func private @rtrand(!Generator, index) -> (index) func.func private @rtdrand(!Generator) -> () - func.func private @shuffle(index, !Generator) -> (!Array) - func.func private @shuffleFree(!Array) -> () + func.func private @shuffle(memref<?xi64>, !Generator) -> () attributes { llvm.emit_c_interface } // // Main driver. @@ -70,15 +58,14 @@ module { %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) - %res = func.call @shuffle(%size, %g) : (index, !Generator) -> !Array + 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. - %r = arith.index_cast %iv : index to i64 - %arr = llvm.getelementptr %res[%r] : (!llvm.ptr, i64) -> !llvm.ptr, i64 - %val = llvm.load %arr : !Array -> i64 + %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) @@ -100,9 +87,9 @@ module { // Release the resources. bufferization.dealloc_tensor %sv : tensor<?xf64, #SparseVector> - func.call @shuffleFree(%res) : (!Array) -> () + memref.dealloc %array : memref<?xi64> func.call @rtdrand(%g) : (!Generator) -> () return } -} \ No newline at end of file +} >From cfca98385c415935cc1223d50dcd7a32227f0885 Mon Sep 17 00:00:00 2001 From: Yinying Li <yinyin...@google.com> Date: Sun, 7 Jan 2024 22:09:59 +0000 Subject: [PATCH 3/6] format --- mlir/include/mlir/ExecutionEngine/CRunnerUtils.h | 11 +++++++---- mlir/lib/ExecutionEngine/CRunnerUtils.cpp | 3 ++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h b/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h index eeb300935dc865..06bef6d9d097f4 100644 --- a/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h +++ b/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h @@ -482,13 +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); -// Uses a random number generator g and returns a random number in the range of [0, 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 *g); -// Uses a random number generator g and std::shuffle to modify memref m in place. -// m will be populated with unique and random numbers in the range of [0, size of m). -extern "C" MLIR_CRUNNERUTILS_EXPORT void _mlir_ciface_shuffle(StridedMemRefType<uint64_t, 1> *m, void *g); +// Uses a random number generator g and std::shuffle to modify memref m +// in place. m will be populated with unique and random numbers +// in the range of [0, size of m). +extern "C" MLIR_CRUNNERUTILS_EXPORT void +_mlir_ciface_shuffle(StridedMemRefType<uint64_t, 1> *m, 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 7949e759e7b36a..c23249f0f46283 100644 --- a/mlir/lib/ExecutionEngine/CRunnerUtils.cpp +++ b/mlir/lib/ExecutionEngine/CRunnerUtils.cpp @@ -176,7 +176,8 @@ extern "C" void rtdrand(void *g) { delete generator; } -extern "C" void _mlir_ciface_shuffle(StridedMemRefType<uint64_t, 1> *m, void *g) { +extern "C" void _mlir_ciface_shuffle(StridedMemRefType<uint64_t, 1> *m, + void *g) { std::mt19937 *generator = static_cast<std::mt19937 *>(g); uint64_t s = m->sizes[0]; std::vector<uint64_t> arr(s); >From cd7b2394436dac729de388e6569a47f07701c38a Mon Sep 17 00:00:00 2001 From: Yinying Li <yinyin...@google.com> Date: Sun, 7 Jan 2024 23:34:07 +0000 Subject: [PATCH 4/6] fix issue for windows --- mlir/lib/ExecutionEngine/CRunnerUtils.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/mlir/lib/ExecutionEngine/CRunnerUtils.cpp b/mlir/lib/ExecutionEngine/CRunnerUtils.cpp index c23249f0f46283..27d1988366ef78 100644 --- a/mlir/lib/ExecutionEngine/CRunnerUtils.cpp +++ b/mlir/lib/ExecutionEngine/CRunnerUtils.cpp @@ -33,6 +33,7 @@ #include <cstdlib> #include <random> #include <string.h> +#include <numeric> #ifdef MLIR_CRUNNERUTILS_DEFINE_FUNCTIONS >From f008880ed26f70c41ef700710138a0bbe653bc74 Mon Sep 17 00:00:00 2001 From: Yinying Li <yinyin...@google.com> Date: Mon, 8 Jan 2024 01:30:54 +0000 Subject: [PATCH 5/6] header --- mlir/lib/ExecutionEngine/CRunnerUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/lib/ExecutionEngine/CRunnerUtils.cpp b/mlir/lib/ExecutionEngine/CRunnerUtils.cpp index 27d1988366ef78..582bc28db86384 100644 --- a/mlir/lib/ExecutionEngine/CRunnerUtils.cpp +++ b/mlir/lib/ExecutionEngine/CRunnerUtils.cpp @@ -31,9 +31,9 @@ #include <cinttypes> #include <cstdio> #include <cstdlib> +#include <numeric> #include <random> #include <string.h> -#include <numeric> #ifdef MLIR_CRUNNERUTILS_DEFINE_FUNCTIONS >From 3f7b0f93cd9d0f25eda06e85bff1ff49571aee5c Mon Sep 17 00:00:00 2001 From: Yinying Li <yinyin...@google.com> Date: Mon, 8 Jan 2024 18:25:12 +0000 Subject: [PATCH 6/6] remove copy --- mlir/include/mlir/ExecutionEngine/CRunnerUtils.h | 8 ++++---- mlir/lib/ExecutionEngine/CRunnerUtils.cpp | 10 ++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h b/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h index 06bef6d9d097f4..812f719e723eb3 100644 --- a/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h +++ b/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h @@ -487,11 +487,11 @@ extern "C" MLIR_CRUNNERUTILS_EXPORT void *rtsrand(uint64_t s); 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 *g); -// Uses a random number generator g and std::shuffle to modify memref m -// in place. m will be populated with unique and random numbers -// in the range of [0, size of m). +// 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> *m, void *g); +_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 582bc28db86384..240f2f08fd90bd 100644 --- a/mlir/lib/ExecutionEngine/CRunnerUtils.cpp +++ b/mlir/lib/ExecutionEngine/CRunnerUtils.cpp @@ -177,14 +177,12 @@ extern "C" void rtdrand(void *g) { delete generator; } -extern "C" void _mlir_ciface_shuffle(StridedMemRefType<uint64_t, 1> *m, +extern "C" void _mlir_ciface_shuffle(StridedMemRefType<uint64_t, 1> *mref, void *g) { std::mt19937 *generator = static_cast<std::mt19937 *>(g); - uint64_t s = m->sizes[0]; - std::vector<uint64_t> arr(s); - std::iota(arr.begin(), arr.end(), 0); - std::shuffle(arr.begin(), arr.end(), *generator); - std::copy(arr.begin(), arr.end(), m->data); + uint64_t s = mref->sizes[0]; + std::iota(mref->data, mref->data + s, 0); + std::shuffle(mref->data, mref->data + s, *generator); } #define IMPL_STDSORT(VNAME, V) \ _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits