Lower function crash in C++ API

Recent days I just started to use this project in C++ and I’m trying to make some simple example by referencing ‘tvm.h’ since there is not a lot of example code for C++.
As I already ask this so far, (Information of C++ API and best way to learn TVM implementation)
hopefully, I’d like to contribute to add documents for this work.

Anyway in this work, I faced uncertain problem, that happends on the lower function and finally this terminated the process improperly.
I’m not sure what is the problem and this way might not be proper to lower the code in C++.
If someone has some intuition about this, please help me.

I just paste my simple main.cc code and the debug log below.

// main.cc
    // define shape
    auto n = tvm::var("n");
    tvm::Array<tvm::Expr> shape;
    shape.push_back(n);

    // define algorithm
    auto A        = tvm::placeholder(shape, tvm::Float(32), "A");
    auto B        = tvm::placeholder(shape, tvm::Float(32), "B");
    tvm::Tensor C = tvm::compute(A->shape, [&A, &B](tvm::Expr i) { return A[i] + B[i]; }, "C");

    // set schedule
    tvm::Schedule s = tvm::create_schedule({C->op});

    tvm::BuildConfig config;
    auto target      = tvm::Target::create("llvm");
    auto target_host = tvm::Target::create("llvm");
    auto args        = tvm::Array<tvm::Tensor>({A, B, C});

    // it doesn't work, what's going on??
    std::unordered_map<tvm::Tensor, tvm::Buffer> binds;
    tvm::Array<tvm::LoweredFunc> lowered = tvm::lower(s, args, "fadd", binds, config);

I compiled the repo normally, and also with non-optimized option and debug flag -g -O0 instead of -O2 and -O3.
By following lldb, I found the problem happened in GetBinds function in build_module.cc , which actually killed the process.
I just saw the reason showed up is Stop reason: EXC_BAD_ACCESS (code=1, address=0x18) .

void GetBinds(const Array<Tensor>& args,
              const std::unordered_map<Tensor, Buffer>& binds,
              Map<Tensor, Buffer>* out_binds,
              Array<NodeRef>* out_arg_list,
              const BuildConfig& config) {
  *out_binds = binds;

  for (const auto &x : args) {
    if (out_binds->find(x) == out_binds->end()) {
      auto buf = BufferWithOffsetAlignment(x->shape, x->dtype, x->op->name,
        config->data_alignment, config->offset_factor); // <- Here, the process stopped
      out_binds->Set(x, buf);
      out_arg_list->push_back(buf);
    } else {
      out_arg_list->push_back((*out_binds)[x]);
    }
  }
}

also show my backtrace

Display settings: variable format=auto, show disassembly=auto, numeric pointer values=off, container summaries=on.
Launching /Users/yamada/tk-home/workspace/tvm/cpp_api/build/test 
2 locations added to breakpoint 1
Stop reason: EXC_BAD_ACCESS (code=1, address=0x18)

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x18)
    frame #0: 0x00000001003ab611 libtvm.dylib`tvm::GetBinds(args=0x00007ffeefbfd960, binds=size=0, out_binds=0x00007ffeefbfd5d0, out_arg_list=0x00007ffeefbfd728, config=0x00007ffeefbfd9c0) at build_module.cc:329
    frame #1: 0x00000001003ac371 libtvm.dylib`tvm::BuildStmt(sch=Schedule @ 0x00007ffeefbfd708, args=0x00007ffeefbfd960, binds=size=0, loop_partition=true, out_arg_list=0x00007ffeefbfd728, config=0x00007ffeefbfd9c0) at build_module.cc:355
    frame #2: 0x00000001003acebd libtvm.dylib`tvm::lower(sch=Schedule @ 0x00007ffeefbfd900, args=0x00007ffeefbfd960, name="fadd", binds=size=0, config=0x00007ffeefbfd9c0) at build_module.cc:392
    frame #3: 0x0000000100002700 test`main at test.cc:30
  * frame #4: 0x00007fff56341015 libdyld.dylib`start + 1

Hi, do you have resolve the issue? Thanks

Not yet but now I’ve started to debug it from python via FFI because I found some difficulty to do it from C++ side.
therefore I think we could close this question.

OK, thanks for your reply.
I have debugged into the inside code, maybe we just need to init a correct BuildConfig for tvm::lower.
@tqchen, could you post some ideas, please? Thanks

I have found why your code crashed in lower, just use BuildConfigNode init your BuildConf, like this tvm::BuildConfig config(std::make_shared<tvm::BuildConfigNode>())

1 Like

Thanks for the comment.
I’ll check it out later!

I tried the suggestion but unfortunately it didn’t work on my environment.
However another guy helped to tell me the solution in here, so you can also try the code with below.

auto config = build_config();
auto target = target::llvm();

Continuing the discussion from Lower function crash in C++ API:

Thanks a lot, it’s really useful, I use the following code, it’s also worked.

	// define shape
	auto n = tvm::var("n");
	tvm::Array<tvm::Expr> shape;
	shape.push_back(n);

	// define algorithm
	auto A = tvm::placeholder(shape, tvm::Float(32), "A");
	auto B = tvm::placeholder(shape, tvm::Float(32), "B");
	tvm::Tensor C = tvm::compute(A->shape, [&A, &B](tvm::Expr i) { return A[i] + B[i]; }, "C");

	// set schedule
	tvm::Schedule s = tvm::create_schedule({ C->op });

//	tvm::BuildConfig config(tvm::BuildConfigNode());
	tvm::BuildConfig config(std::make_shared<tvm::BuildConfigNode>());
	auto target = tvm::Target::create("llvm");
	auto target_host = tvm::Target::create("llvm");
	auto args = tvm::Array<tvm::Tensor>({ A, B, C });

	// it doesn't work, what's going on??
	std::unordered_map<tvm::Tensor, tvm::Buffer> binds;
	tvm::Array<tvm::LoweredFunc> lowered = tvm::lower(s, args, "fadd", binds, config);
	tvm::runtime::Module mod = tvm::build(lowered, target, target_host, config);
	auto fadd = mod.GetFunction("fadd", true);
	std::vector<tvm::runtime::Module> imported_modules = mod->imports();
	if (imported_modules.empty())
	{
		std::cout << "Import mode failed" << std::endl;
	}
	else
	{
		std::cout << imported_modules[0]->GetSource() << std::endl;
	}

	return 0;