Skip to content

Commit 027d127

Browse files
committed
tensor,module: add a utility to allow for debugging generated kernels
This commit adds a function `debugCompileSource` to a `Tensor` that allows for the `Tensor` to use a kernel from a provided source file instead of generating a new one. This allows developers to add prints/assertions to TACO generated code to debug faster. Inspired by Amalee's PR (tensor-compiler#302), I would have found a command like this very useful for debugging generated code.
1 parent 468ad7f commit 027d127

File tree

4 files changed

+65
-19
lines changed

4 files changed

+65
-19
lines changed

include/taco/codegen/module.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ class Module {
2525

2626
/// Compile the source into a library, returning its full path
2727
std::string compile();
28+
29+
/// Compile the sources at the given prefix and link the compiled code. A
30+
/// libPrefix is of the form path/prefix, where files path/prefix.{c, h} are
31+
/// present. debugCompileSourceFile can be used to recompile an existing
32+
/// generated code file with handwritten changes to debug.
33+
void debugCompileSourceFile(std::string libPrefix);
2834

2935
/// Compile the module into a source file located at the specified location
3036
/// path and prefix. The generated source will be path/prefix.{.c|.bc, .h}
@@ -82,6 +88,12 @@ class Module {
8288

8389
void setJITLibname();
8490
void setJITTmpdir();
91+
92+
/// compileAndLink compiles the files at prefix into a library file named
93+
/// output, and dynamically links output into the TACO process. libPrefix
94+
/// is of the form path/prefix, where files path/prefix.{c, cu, h, cpp}
95+
/// are placed to be compiled.
96+
void compileAndLink(std::string libPrefix, std::string output);
8597
};
8698

8799
} // namespace ir

include/taco/tensor.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,21 @@ class TensorBase {
413413

414414
void compile(IndexStmt stmt, bool assembleWhileCompute=false);
415415

416+
/// debugCompileSource can be used to edit TACO generated code (to add prints
417+
/// or assertions etc) and use the TACO machinery to execute the edited code.
418+
/// debugCompileSource takes in a string libPrefix that is the path to a
419+
/// group of TACO generated files. In particular, TACO generates files like
420+
/// path/prefix.{c, h, ...}. In this case, libPrefix should equal "path/prefix".
421+
/// An example workflow is as follows:
422+
/// Tensor a; Tensor b; IndexVar i;
423+
/// a(i) = b(i);
424+
/// // a.compile(); Compile the expression once to generate code.
425+
/// a.debugCompileSource("/tmp/....");
426+
/// a.evaluate();
427+
// TODO (rohany): This should only get compiled in a test/debug build, but
428+
// I'm not sure that we have the flags set up to do this.
429+
void debugCompileSource(std::string libPrefix);
430+
416431
/// Assemble the tensor storage, including index and value arrays.
417432
void assemble();
418433

src/codegen/module.cpp

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -116,52 +116,62 @@ void writeShims(vector<Stmt> funcs, string path, string prefix) {
116116
string Module::compile() {
117117
string prefix = tmpdir+libname;
118118
string fullpath = prefix + ".so";
119+
120+
// open the output file & write out the source
121+
compileToSource(tmpdir, libname);
119122

123+
// write out the shims
124+
writeShims(funcs, tmpdir, libname);
125+
126+
this->compileAndLink(prefix, fullpath);
127+
128+
return fullpath;
129+
}
130+
131+
void Module::compileAndLink(std::string libPrefix, std::string output) {
132+
// Construct the command to compile the source files.
120133
string cc;
121134
string cflags;
122135
string file_ending;
123136
string shims_file;
124137
if (should_use_CUDA_codegen()) {
125138
cc = util::getFromEnv("TACO_NVCC", "nvcc");
126-
cflags = util::getFromEnv("TACO_NVCCFLAGS",
127-
get_default_CUDA_compiler_flags());
139+
cflags = util::getFromEnv("TACO_NVCCFLAGS", get_default_CUDA_compiler_flags());
128140
file_ending = ".cu";
129-
shims_file = prefix + "_shims.cpp";
141+
shims_file = libPrefix + "_shims.cpp";
130142
}
131143
else {
132144
cc = util::getFromEnv(target.compiler_env, target.compiler);
133-
cflags = util::getFromEnv("TACO_CFLAGS",
134-
"-O3 -ffast-math -std=c99") + " -shared -fPIC";
145+
cflags = util::getFromEnv("TACO_CFLAGS", "-O3 -ffast-math -std=c99") + " -shared -fPIC";
135146
#if USE_OPENMP
136147
cflags += " -fopenmp";
137148
#endif
138149
file_ending = ".c";
139150
shims_file = "";
140151
}
141-
142-
string cmd = cc + " " + cflags + " " +
143-
prefix + file_ending + " " + shims_file + " " +
144-
"-o " + fullpath + " -lm";
145152

146-
// open the output file & write out the source
147-
compileToSource(tmpdir, libname);
148-
149-
// write out the shims
150-
writeShims(funcs, tmpdir, libname);
151-
152-
// now compile it
153+
auto cmd = cc + " " + cflags + " " +
154+
libPrefix + file_ending + " " + shims_file + " " +
155+
"-o " + output + " -lm";
156+
157+
// Execute the compilation command.
153158
int err = system(cmd.data());
154159
taco_uassert(err == 0) << "Compilation command failed:\n" << cmd
155160
<< "\nreturned " << err;
156161

157-
// use dlsym() to open the compiled library
162+
// Use dlsym() to dynamically link the compiled library.
158163
if (lib_handle) {
164+
// Close the existing handle one is open already.
159165
dlclose(lib_handle);
160166
}
161-
lib_handle = dlopen(fullpath.data(), RTLD_NOW | RTLD_LOCAL);
167+
168+
lib_handle = dlopen(output.data(), RTLD_NOW | RTLD_LOCAL);
162169
taco_uassert(lib_handle) << "Failed to load generated code";
170+
}
163171

164-
return fullpath;
172+
void Module::debugCompileSourceFile(string libPrefix) {
173+
// Directly compile the files at the target libPrefix.
174+
this->compileAndLink(libPrefix, libPrefix + ".so");
165175
}
166176

167177
void Module::setSource(string source) {

src/tensor.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@ void TensorBase::compile() {
573573
stmt = parallelizeOuterLoop(stmt);
574574
compile(stmt, content->assembleWhileCompute);
575575
}
576+
576577
void TensorBase::compile(taco::IndexStmt stmt, bool assembleWhileCompute) {
577578
if (!needsCompile()) {
578579
return;
@@ -602,6 +603,14 @@ void TensorBase::compile(taco::IndexStmt stmt, bool assembleWhileCompute) {
602603
cacheComputeKernel(concretizedAssign, content->module);
603604
}
604605

606+
void TensorBase::debugCompileSource(std::string libPrefix) {
607+
// We're directly compiling user provided source, so mark compilation as done.
608+
this->setNeedsCompile(false);
609+
// Make a new module and compile the source.
610+
content->module = make_shared<Module>();
611+
content->module->debugCompileSourceFile(libPrefix);
612+
}
613+
605614
taco_tensor_t* TensorBase::getTacoTensorT() {
606615
return getStorage();
607616
}

0 commit comments

Comments
 (0)