Skip to content

Commit 270b81c

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 270b81c

File tree

4 files changed

+67
-18
lines changed

4 files changed

+67
-18
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: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -116,52 +116,64 @@ 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");
126139
cflags = util::getFromEnv("TACO_NVCCFLAGS",
127-
get_default_CUDA_compiler_flags());
140+
get_default_CUDA_compiler_flags());
128141
file_ending = ".cu";
129-
shims_file = prefix + "_shims.cpp";
142+
shims_file = libPrefix + "_shims.cpp";
130143
}
131144
else {
132145
cc = util::getFromEnv(target.compiler_env, target.compiler);
133146
cflags = util::getFromEnv("TACO_CFLAGS",
134-
"-O3 -ffast-math -std=c99") + " -shared -fPIC";
147+
"-O3 -ffast-math -std=c99") + " -shared -fPIC";
135148
#if USE_OPENMP
136149
cflags += " -fopenmp";
137150
#endif
138151
file_ending = ".c";
139152
shims_file = "";
140153
}
141-
142-
string cmd = cc + " " + cflags + " " +
143-
prefix + file_ending + " " + shims_file + " " +
144-
"-o " + fullpath + " -lm";
145154

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
155+
auto cmd = cc + " " + cflags + " " +
156+
libPrefix + file_ending + " " + shims_file + " " +
157+
"-o " + output + " -lm";
158+
159+
// Execute the compilation command.
153160
int err = system(cmd.data());
154161
taco_uassert(err == 0) << "Compilation command failed:\n" << cmd
155-
<< "\nreturned " << err;
162+
<< "\nreturned " << err;
156163

157-
// use dlsym() to open the compiled library
164+
// Use dlsym() to dynamically link the compiled library.
158165
if (lib_handle) {
166+
// Close the existing handle one is open already.
159167
dlclose(lib_handle);
160168
}
161-
lib_handle = dlopen(fullpath.data(), RTLD_NOW | RTLD_LOCAL);
169+
170+
lib_handle = dlopen(output.data(), RTLD_NOW | RTLD_LOCAL);
162171
taco_uassert(lib_handle) << "Failed to load generated code";
172+
}
163173

164-
return fullpath;
174+
void Module::debugCompileSourceFile(string libPrefix) {
175+
// Directly compile the files at the target libPrefix.
176+
this->compileAndLink(libPrefix, libPrefix + ".so");
165177
}
166178

167179
void Module::setSource(string source) {
@@ -170,6 +182,7 @@ void Module::setSource(string source) {
170182
}
171183

172184
string Module::getSource() {
185+
cout << this->tmpdir << endl;
173186
return source.str();
174187
}
175188

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)