Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DAPHNE-#854] Add Passes for Matrix Result Property Recording and Insertion in IR #855

Open
wants to merge 72 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
3a1c255
first try for is Nan feature
StoeckOverflow Jul 3, 2024
290c69e
small fix in test
StoeckOverflow Jul 7, 2024
47e3d35
refined testing
StoeckOverflow Jul 7, 2024
d4546a0
small fix
StoeckOverflow Jul 7, 2024
b7a10aa
Merge remote-tracking branch 'origin/main' into 768-is-Nan-Feature
StoeckOverflow Jul 7, 2024
b830d8b
changes the mnemonic of the DaphneIR operation to ewIsnan
StoeckOverflow Jul 9, 2024
3540afe
First Draft
StoeckOverflow Jul 11, 2024
83f8b36
Canonicalization for Isnan
StoeckOverflow Jul 12, 2024
02a83c6
json support
StoeckOverflow Jul 12, 2024
fb26846
clean up DaphneDialect
StoeckOverflow Jul 12, 2024
b55df68
debug messages for pass
StoeckOverflow Jul 12, 2024
67097d6
First Draft of RecordOp
StoeckOverflow Jul 16, 2024
f88e69d
bugfixes
StoeckOverflow Jul 16, 2024
c332e39
a bit more work on the record op
StoeckOverflow Jul 18, 2024
e9538bc
cut out LLVM Lowering of LowerToLLVMPass
StoeckOverflow Jul 19, 2024
d973c0a
C++ Kernel for RecordProperties first draft
StoeckOverflow Jul 19, 2024
7230651
changes from local WSL
StoeckOverflow Jul 23, 2024
169adb6
current state
StoeckOverflow Jul 23, 2024
7c41966
clean
StoeckOverflow Jul 25, 2024
2aaab9e
op id is not int64_t, refactored RecordPropertiesPass.cpp
StoeckOverflow Jul 25, 2024
8329bac
refactored RecordPropetiesPass and created InsertPropertiesPass; work…
StoeckOverflow Jul 30, 2024
e816f7b
updates to the testing
StoeckOverflow Aug 9, 2024
a324667
first work for EwBinary and EwUnary Sparse Matrices Support
StoeckOverflow Aug 11, 2024
f6590c6
Merge branch 'ewBinarySparsityOps' into record-Properties-Op
StoeckOverflow Aug 12, 2024
4f73df7
Fixed Typos of merge
StoeckOverflow Aug 12, 2024
7bf04c5
another typo
StoeckOverflow Aug 12, 2024
e111791
bugfixes
StoeckOverflow Aug 12, 2024
f4a8b3f
added getArgument and getDescription method to RecordPropertiesPass
StoeckOverflow Aug 18, 2024
d584289
refined test and code logic
StoeckOverflow Aug 19, 2024
a74dbe2
Merge branch 'ewBinarySparsityOps' into record-Properties-Op
StoeckOverflow Aug 19, 2024
c5d6adb
Extended the EwBinaryMat Kernel
StoeckOverflow Aug 19, 2024
96c0512
extended the BinaryMatKernel
StoeckOverflow Aug 19, 2024
4570cec
updated kernels.json
StoeckOverflow Aug 19, 2024
ad0a8cb
updated kernels.json
StoeckOverflow Aug 19, 2024
932fd36
refined testing scripts
StoeckOverflow Aug 20, 2024
3016ae5
Quick extension in ReadCsvFile regarding the Input read of Dense Matr…
StoeckOverflow Aug 20, 2024
27ab1bd
fixed typos in kernels.json
StoeckOverflow Aug 20, 2024
65457ec
Merge branch 'daphne-eu:main' into 811-extend-ewmat-kernels-for-spars…
StoeckOverflow Aug 20, 2024
6f15e27
Merge branch 'daphne-eu:main' into record-Properties-Op
StoeckOverflow Aug 20, 2024
2adf64d
changed resize approach to worstCaseNNZ allocation approach
StoeckOverflow Aug 28, 2024
1c0dd38
Merge branch '811-extend-ewmat-kernels-for-sparse-dense-addition' int…
StoeckOverflow Aug 28, 2024
89b1f91
new plot method and new plot
StoeckOverflow Aug 29, 2024
9634bee
change at propertyRecordingExperimentImport.py
StoeckOverflow Aug 29, 2024
3c2431c
changed IR Executor state of PropertyPass and improved Experiment Script
StoeckOverflow Sep 3, 2024
f4673b7
Merge branch 'daphne-eu:main' into record-Properties-Op
StoeckOverflow Sep 3, 2024
932ad54
refined plotting
StoeckOverflow Sep 3, 2024
bb1d89a
Merge branch 'record-Properties-Op' of https://github.com/StoeckOverf…
StoeckOverflow Sep 3, 2024
edaf6a1
fixed error in the rounding of the plotted sparsity values
StoeckOverflow Sep 3, 2024
82f3afe
refined plot
StoeckOverflow Sep 3, 2024
5279503
mnc experiment and overhead experiment
StoeckOverflow Sep 11, 2024
5d4c5c6
properyRecoridngExperiment refined
StoeckOverflow Sep 11, 2024
686f0d7
more plots and testscripts
StoeckOverflow Sep 11, 2024
cc6e0d9
mnc script and recordProperties Improvement
StoeckOverflow Sep 11, 2024
c14ca89
new Kernels for MatMul and UnaryMat
StoeckOverflow Sep 11, 2024
204bf42
Merge branch 'daphne-eu:main' into record-Properties-Op
StoeckOverflow Sep 11, 2024
d83999a
changed naming of testscripts and refined Property Insert regarding L…
StoeckOverflow Sep 18, 2024
1c81cac
updated PropertyRecording and Insert
StoeckOverflow Oct 1, 2024
e42b4f1
new Daphne Ops for givin Matrix Representation Hint
StoeckOverflow Oct 2, 2024
3c5e597
Optimizations on the Daphne Rep Hint Op
StoeckOverflow Oct 2, 2024
83aae0f
overhead measurement script change
StoeckOverflow Oct 2, 2024
e76d9fe
added Tests to RepOpHint and Property Recording, refined Overhead Mea…
StoeckOverflow Oct 14, 2024
d49dc45
clean up
StoeckOverflow Oct 14, 2024
cad6666
Merge remote-tracking branch 'origin/main' into property-recording-pr…
StoeckOverflow Oct 14, 2024
607b7ca
doc + bug fixes in test
StoeckOverflow Oct 14, 2024
2451684
refined InsertProperties Pass Logic
StoeckOverflow Oct 24, 2024
d904a31
added codegen tests for InsertPropertiesPass
StoeckOverflow Oct 24, 2024
d5c02a4
removed comments
StoeckOverflow Oct 24, 2024
76ae11a
Missing file added
StoeckOverflow Oct 24, 2024
44fbf3f
updated CMake Lists
StoeckOverflow Oct 24, 2024
5de74d1
added Codegen to CmakeLists
StoeckOverflow Oct 24, 2024
427260e
cmake list corrected again
StoeckOverflow Oct 24, 2024
0c483a8
added codegen to tests
StoeckOverflow Oct 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion UserConfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
"explain_vectorized": false,
"explain_obj_ref_mgnt": false,
"explain_mlir_codegen": false,
"enable_property_recording": false,
"enable_property_insert": false,
"properties_file_path": "properties.json",
"taskPartitioningScheme": "STATIC",
"numberOfThreads": -1,
"minimumTaskSize": 1,
Expand Down Expand Up @@ -71,5 +74,5 @@
"format": "%^[%n %L]:%$ %v"
}
],
"sparsity_threshold": 0.25
"sparsity_threshold": 0.49
}
8 changes: 8 additions & 0 deletions doc/RunningDaphneLocally.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ Note that some of the more specific options are described in the documentation p

Turns on the automatic selection of a suitable matrix representation (currently dense or sparse (CSR)). *Experimental feature.*

- **`--enable_property_recording`**

Enables recording of certain properties (currently only sparsity) from all matrix result objects in the Intermediate Representation (IR). The recorded properties are saved in a JSON file named properties.json located in the root directory of Daphne.

- **`--enable_property_insert`** and **`--properties_file_path=<path/to/propertiesFile>`**

Allows the insertion of previously recorded properties into operations with matrix results from a JSON file. By default, the file used is properties.json in the Daphne root directory. Optionally, a different file can be specified using the `--properties_file_path` argument.

## Return Codes

If `daphne` terminates normally, one of the following status codes is returned:
Expand Down
3 changes: 3 additions & 0 deletions src/api/cli/DaphneUserConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ struct DaphneUserConfig {
bool explain_obj_ref_mgnt = false;
bool explain_mlir_codegen = false;
bool statistics = false;
bool enable_property_recording = false;
bool enable_property_insert = false;
std::string properties_file_path = "properties.json";

bool force_cuda = false;

Expand Down
58 changes: 45 additions & 13 deletions src/api/internal/daphne_internal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <util/DaphneLogger.h>
#include <util/KernelDispatchMapping.h>
#include <util/Statistics.h>
#include <util/PropertyLogger.h>

#include "mlir/ExecutionEngine/ExecutionEngine.h"
#include "mlir/IR/Builders.h"
Expand Down Expand Up @@ -310,17 +311,39 @@ int startDAPHNE(int argc, const char **argv, DaphneLibResult *daphneLibRes, int
"e.g., `--args x=1,y=2.2`"),
CommaSeparated);
const std::string configFileInitValue = "-";
static opt<string> configFile("config", cat(daphneOptions),
desc("A JSON file that contains the DAPHNE configuration"), value_desc("filename"),
llvm::cl::init(configFileInitValue));

static opt<bool> enableStatistics("statistics", cat(daphneOptions), desc("Enables runtime statistics output."));

static opt<bool> enableProfiling("enable-profiling", cat(daphneOptions), desc("Enable profiling support"));
static opt<bool> timing("timing", cat(daphneOptions),
desc("Enable timing of high-level steps (start-up, "
"parsing, compilation, execution) and print "
"the times to stderr in JSON format"));
static opt<string> configFile(
"config", cat(daphneOptions),
desc("A JSON file that contains the DAPHNE configuration"),
value_desc("filename"),
llvm::cl::init(configFileInitValue)
);

static opt<bool> enableStatistics(
"statistics", cat(daphneOptions),
desc("Enables runtime statistics output."));

static opt<bool> enablePropertyRecording(
"enable_property_recording", cat(daphneOptions),
desc("records runtime properties and outputs it in JSON."));

static opt<bool> enablePropertyInsert(
"enable_property_insert", cat(daphneOptions),
desc("inserts runtime properties from properties.json of previous run."));

static opt<std::string> properties_file_path(
"properties_file_path", cat(daphneOptions),
llvm::cl::desc("Path to the Properties File in JSON for the Property insert."),
llvm::cl::init("properties.json")
);

static opt<bool> enableProfiling (
"enable-profiling", cat(daphneOptions),
desc("Enable profiling support")
);
static opt<bool> timing (
"timing", cat(daphneOptions),
desc("Enable timing of high-level steps (start-up, parsing, compilation, execution) and print the times to stderr in JSON format")
);

// Positional arguments ---------------------------------------------------

Expand Down Expand Up @@ -385,6 +408,7 @@ int startDAPHNE(int argc, const char **argv, DaphneLibResult *daphneLibRes, int
user_config.matmul_tile = true;
}
user_config.use_mlir_hybrid_codegen = performHybridCodegen;


if (!libDir.getValue().empty())
user_config.libdir = libDir.getValue();
Expand Down Expand Up @@ -478,6 +502,11 @@ int startDAPHNE(int argc, const char **argv, DaphneLibResult *daphneLibRes, int
}

user_config.statistics = enableStatistics;
user_config.enable_property_recording = enablePropertyRecording;
user_config.enable_property_insert = enablePropertyInsert;

if (user_config.enable_property_insert)
user_config.properties_file_path = properties_file_path.getValue();

if (user_config.use_distributed && distributedBackEndSetup == ALLOCATION_TYPE::DIST_MPI) {
#ifndef USE_MPI
Expand Down Expand Up @@ -652,9 +681,12 @@ int startDAPHNE(int argc, const char **argv, DaphneLibResult *daphneLibRes, int
if (user_config.statistics)
Statistics::instance().dumpStatistics(KernelDispatchMapping::instance());

// explicitly destroying the moduleOp here due to valgrind complaining about
// a memory leak otherwise.
if (user_config.enable_property_recording)
PropertyLogger::instance().savePropertiesAsJson("properties.json");

// explicitly destroying the moduleOp here due to valgrind complaining about a memory leak otherwise.
moduleOp->destroy();

return StatusCode::SUCCESS;
}

Expand Down
3 changes: 2 additions & 1 deletion src/api/python/daphne/utils/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
VALID_ARITHMETIC_TYPES = Union['DAGNode', int, float]
VALID_COMPUTED_TYPES = Union['Matrix', 'Frame', 'Scalar']

TMP_PATH = os.path.join("/tmp/", "DaphneLib")
#TMP_PATH = os.path.join("/tmp/", "DaphneLib")
TMP_PATH = os.path.join("/home", "dominic", "daphne", "tmp", "DaphneLib")
os.makedirs(TMP_PATH, exist_ok=True)

_PROTOTYPE_PATH_ENV_VAR_NAME = "DAPHNELIB_DIR_PATH"
Expand Down
17 changes: 14 additions & 3 deletions src/compiler/execution/DaphneIrExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,16 @@ bool DaphneIrExecutor::runPasses(mlir::ModuleOp module) {
pm.addNestedPass<mlir::func::FuncOp>(mlir::daphne::createInferencePass());
pm.addPass(mlir::createCanonicalizerPass());

if(userConfig_.enable_property_recording)
pm.addPass(mlir::daphne::createRecordPropertiesPass());

if(userConfig_.enable_property_insert)
{
pm.addPass(mlir::daphne::createInsertPropertiesPass(userConfig_.properties_file_path));
pm.addNestedPass<mlir::func::FuncOp>(mlir::daphne::createInferencePass());
pm.addNestedPass<mlir::func::FuncOp>(mlir::createCanonicalizerPass());
}

if (selectMatrixRepresentations_) {
pm.addNestedPass<mlir::func::FuncOp>(mlir::daphne::createSelectMatrixRepresentationsPass(userConfig_));
pm.addNestedPass<mlir::func::FuncOp>(mlir::createCanonicalizerPass());
Expand Down Expand Up @@ -175,22 +185,23 @@ bool DaphneIrExecutor::runPasses(mlir::ModuleOp module) {
pm.addPass(mlir::createCanonicalizerPass());
pm.addPass(mlir::createCSEPass());



if (userConfig_.use_obj_ref_mgnt)
pm.addNestedPass<mlir::func::FuncOp>(mlir::daphne::createManageObjRefsPass());
if (userConfig_.explain_obj_ref_mgnt)
pm.addPass(mlir::daphne::createPrintIRPass("IR after managing object references:"));

pm.addNestedPass<mlir::func::FuncOp>(mlir::daphne::createRewriteToCallKernelOpPass(userConfig_, usedLibPaths));
if (userConfig_.explain_kernels)
pm.addPass(mlir::daphne::createPrintIRPass("IR after kernel lowering:"));

pm.addPass(
mlir::daphne::createPrintIRPass("IR after kernel lowering:"));
pm.addPass(mlir::createConvertSCFToCFPass());
pm.addNestedPass<mlir::func::FuncOp>(mlir::LLVM::createRequestCWrappersPass());
pm.addPass(mlir::daphne::createLowerToLLVMPass(userConfig_));
pm.addPass(mlir::createReconcileUnrealizedCastsPass());
if (userConfig_.explain_llvm)
pm.addPass(mlir::daphne::createPrintIRPass("IR after llvm lowering:"));

// Initialize the use of each distinct kernels library to false.
usedLibPaths = userConfig_.kernelCatalog.getLibPaths();

Expand Down
2 changes: 2 additions & 0 deletions src/compiler/explanation/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

add_mlir_dialect_library(MLIRDaphneExplain
PrintIRPass.cpp
RecordPropertiesPass.cpp
InsertPropertiesPass.cpp

DEPENDS
MLIRDaphneOpsIncGen
Expand Down
183 changes: 183 additions & 0 deletions src/compiler/explanation/InsertPropertiesPass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/Value.h"
#include "mlir/IR/Visitors.h"
#include "mlir/Pass/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstdint>
#include <fstream>
#include <ir/daphneir/Daphne.h>
#include <ir/daphneir/Passes.h>
#include <mlir/Dialect/SCF/IR/SCF.h>
#include <nlohmannjson/json.hpp>
#include <string>

namespace mlir {
#define GEN_PASS_DECL_INSERTPROPERTIESPASS
#define GEN_PASS_DEF_INSERTPROPERTIESPASS
#include "ir/daphneir/Passes.h.inc"
} // namespace mlir

using namespace mlir;

nlohmann::json readPropertiesFromFile(const std::string &filename) {
std::ifstream file(filename);
if (!file.is_open()) {
throw std::runtime_error("Failed to open file: " + filename);
}

nlohmann::json properties;
file >> properties;
return properties;
}

struct PropertyEntry {
uint32_t valueID;
nlohmann::json properties;

bool operator<(const PropertyEntry &other) const {
return valueID < other.valueID;
}
};

namespace {
struct InsertPropertiesPass
: public impl::InsertPropertiesPassBase<InsertPropertiesPass> {
InsertPropertiesPass() = default;

public:
explicit InsertPropertiesPass(std::string properties_file_path)
: impl::InsertPropertiesPassBase<InsertPropertiesPass>() {
this->properties_file_path = properties_file_path;
};
void runOnOperation() override;
};
} // end of anonymous namespace

void InsertPropertiesPass::runOnOperation() {
func::FuncOp func = getOperation();
OpBuilder builder(func.getContext());

nlohmann::json propertiesJson =
readPropertiesFromFile(this->properties_file_path);
llvm::DenseMap<std::pair<Value, Operation *>, Value> castOpMap;

std::vector<PropertyEntry> properties;
for (auto it = propertiesJson.begin(); it != propertiesJson.end(); ++it) {
uint32_t valueID = std::stoi(it.key());
properties.push_back({valueID, it.value()});
}
std::sort(properties.begin(), properties.end());
size_t propertyIndex = 0;

auto insertRecordedProperties = [&](Operation *op) {
size_t numResults = op->getNumResults();
for (unsigned i = 0; i < numResults && propertyIndex < properties.size();
++i) {
Value res = op->getResult(i);
nlohmann::json &prop = properties[propertyIndex].properties;
auto it = prop.begin();
while (it != prop.end()) {
const std::string &key = it.key();
const nlohmann::json &value = it.value();
if (key == "sparsity") {
if (value.is_null()) {
llvm::errs() << "Error: 'sparsity' is null for property index "
<< propertyIndex << "\n";
++it;
continue;
} else if (!value.is_number()) {
llvm::errs()
<< "Error: 'sparsity' is not a number for property index "
<< propertyIndex << "\n";
++it;
continue;
}

if (res.getType().isa<daphne::MatrixType>()) {
auto mt = res.getType().dyn_cast<daphne::MatrixType>();
double sparsity = value.get<double>();
if (mt) {
if ((llvm::isa<scf::ForOp>(op) || llvm::isa<scf::WhileOp>(op) ||
llvm::isa<scf::IfOp>(op))) {
builder.setInsertionPointAfter(op);
builder.create<daphne::CastOp>(op->getLoc(),
mt.withSparsity(sparsity), res);
}

else {
for (auto &use : res.getUses()) {
Operation *userOp = use.getOwner();
if (isa<scf::ForOp>(userOp) || isa<scf::IfOp>(userOp) ||
isa<scf::WhileOp>(userOp)) {
auto key = std::make_pair(res, userOp);

Value castOpValue;
if (castOpMap.count(key)) {
castOpValue = castOpMap[key];
} else {
builder.setInsertionPoint(userOp);
castOpValue =
builder.create<daphne::CastOp>(op->getLoc(), mt, res);
castOpMap[key] = castOpValue;
}

userOp->setOperand(use.getOperandNumber(), castOpValue);
}
}
}

++propertyIndex;
}
}
}
++it;
}
}
};

func.walk<WalkOrder::PreOrder>([&](Operation *op) -> WalkResult {
if (propertyIndex >= properties.size())
return WalkResult::advance();

// Skip specific ops that should not be processed
if (isa<daphne::RecordPropertiesOp>(op) || op->hasAttr("daphne.value_ids"))
return WalkResult::advance();

if (auto castOp = dyn_cast<daphne::CastOp>(op)) {
if (castOp.isRemovePropertyCast()) {
return WalkResult::advance();
}
}

// Handle loops (scf.for and scf.while) and If blocks as black boxes
if (isa<scf::ForOp>(op) || isa<scf::WhileOp>(op) || isa<scf::IfOp>(op)) {
insertRecordedProperties(op);
return WalkResult::skip();
}

if (auto funcOp = llvm::dyn_cast<func::FuncOp>(op)) {
// Check if this is the @main function or a UDF
if (funcOp.getName() == "main") {
return WalkResult::advance();
} else {
return WalkResult::skip();
}
}

// Process all other operations that output matrix types
insertRecordedProperties(op);
return WalkResult::advance();
});

if (propertyIndex < properties.size()) {
llvm::errs() << "Warning: Not all properties were applied." << "\n";
}
}

std::unique_ptr<OperationPass<func::FuncOp>>
mlir::daphne::createInsertPropertiesPass(std::string propertiesFilePath) {
return std::make_unique<InsertPropertiesPass>(propertiesFilePath);
}
Loading