/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #ifdef USE_MICRO_STANDALONE_RUNTIME // Use system(..), `gcc -shared -fPIC`, thus restrict the test to OS X for now. #if defined(__APPLE__) && defined(__MACH__) #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include TVM_REGISTER_GLOBAL("test.sch").set_body([](tvm::TVMArgs args, tvm::TVMRetValue* rv) { *rv = ::tvm::topi::generic::schedule_injective(args[0], args[1]); }); TEST(MicroStandaloneRuntime, BuildModule) { using namespace tvm; auto tensor_type = relay::TensorType({2, 3}, ::tvm::runtime::DataType::Float(32)); auto a = relay::Var("a", tensor_type); auto b = relay::Var("b", tensor_type); auto add_op = relay::Op::Get("add"); auto x = relay::Call(add_op, {a, b}, tvm::Attrs(), {}); auto c = relay::Var("c", tensor_type); auto y = relay::Call(add_op, {x, c}, tvm::Attrs(), {}); auto func = relay::Function(relay::FreeVars(y), y, relay::Type(), {}); auto A = tvm::runtime::NDArray::Empty({2, 3}, {kDLFloat, 32, 1}, {kDLCPU, 0}); auto B = tvm::runtime::NDArray::Empty({2, 3}, {kDLFloat, 32, 1}, {kDLCPU, 0}); auto C = tvm::runtime::NDArray::Empty({2, 3}, {kDLFloat, 32, 1}, {kDLCPU, 0}); auto pA = static_cast(A->data); auto pB = static_cast(B->data); auto pC = static_cast(C->data); for (int i = 0; i < 6; ++i) { pA[i] = i; pB[i] = i + 1; pC[i] = i + 2; } // get schedule auto reg = tvm::runtime::Registry::Get("relay.op._Register"); auto s_i = tvm::runtime::Registry::Get("test.sch"); if (!reg) { LOG(FATAL) << "no _Register"; } if (!s_i) { LOG(FATAL) << "no test_sch"; } (*reg)("add", "FTVMSchedule", *s_i, 10); // build auto pfb = tvm::runtime::Registry::Get("relay.build_module._BuildModule"); tvm::runtime::Module build_mod = (*pfb)(); auto build_f = build_mod.GetFunction("build", false); auto json_f = build_mod.GetFunction("get_graph_json", false); auto mod_f = build_mod.GetFunction("get_module", false); Map targets; Target llvm_tgt = Target("llvm"); targets.Set(0, llvm_tgt); build_f(func, targets, llvm_tgt, runtime::kTvmExecutorGraph, ""); std::string json = json_f(); tvm::runtime::Module mod = mod_f(); std::string o_fname = std::tmpnam(nullptr); std::string so_fname = std::tmpnam(nullptr); mod->SaveToFile(o_fname, "o"); const std::vector args = {"gcc", "-shared", "-fPIC", "-o", so_fname, o_fname}; std::stringstream s; for (auto& c : args) { s << c << " "; } const auto ss = s.str(); const auto ret = system(ss.c_str()); ASSERT_EQ(ret, 0); // Now, execute the minimal runtime. auto* dsoModule = MicroTVMRuntimeDSOModuleCreate(so_fname.c_str(), so_fname.size()); ASSERT_NE(dsoModule, nullptr); auto* handle = MicroTVMRuntimeCreate(json.c_str(), json.size(), dsoModule); ASSERT_NE(handle, nullptr); MicroTVMRuntimeSetInput(handle, 0, const_cast(A.operator->())); MicroTVMRuntimeSetInput(handle, 1, const_cast(B.operator->())); MicroTVMRuntimeSetInput(handle, 2, const_cast(C.operator->())); MicroTVMRuntimeRun(handle); auto Y = tvm::runtime::NDArray::Empty({2, 3}, {kDLFloat, 32, 1}, {kDLCPU, 0}); MicroTVMRuntimeGetOutput(handle, 0, const_cast(Y.operator->())); auto* pY = static_cast(Y->data); for (int i = 0; i < 6; ++i) { CHECK_LT(fabs(pY[i] - (i + (i + 1) + (i + 2))), 1e-4); } MicroTVMRuntimeDestroy(handle); MicroTVMRuntimeDSOModuleDestroy(dsoModule); } #endif #endif