blob: 860596c611697ef7f3f7b1894c66836425fa0cea [file]
/*
* 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.
*/
/*!
* \file tvm/relax/transform/update_vdevice.cc
* \brief Update Virtual Device pass.
*/
#include <tvm/ffi/reflection/registry.h>
#include <tvm/relax/expr.h>
#include <tvm/relax/expr_functor.h>
#include <tvm/relax/transform.h>
namespace tvm {
namespace relax {
class VDeviceMutator : public ExprMutator {
public:
VDeviceMutator(const IRModule& mod, VDevice new_vdevice, int64_t index)
: ExprMutator(mod), mod_(mod), new_vdevice_(new_vdevice) {
ffi::Array<GlobalInfo> vdevices = mod->global_infos["vdevice"];
old_vdevice_ = vdevices[index].as_or_throw<VDevice>();
}
using ExprMutator::VisitExpr_;
Expr VisitExpr(const Expr& expr) final {
auto visited_expr = ExprMutator::VisitExpr(expr);
if (!visited_expr->ty.IsMissing()) {
auto* tinfo = GetTypeAs<TensorTypeNode>(visited_expr);
bool unchanged = true;
if (tinfo != nullptr) {
if (tinfo->vdevice.has_value()) {
VDevice cur_vdevice = tinfo->vdevice.value();
if (cur_vdevice == old_vdevice_) {
unchanged = false;
}
}
}
if (!unchanged) {
if (tinfo->shape.has_value()) {
visited_expr->ty =
TensorType(tinfo->shape.value(), tinfo->dtype, new_vdevice_, tinfo->span);
} else {
visited_expr->ty = TensorType(tinfo->dtype, tinfo->ndim, new_vdevice_, tinfo->span);
}
}
}
return visited_expr;
}
IRModule Run() {
for (const auto& [gv, func] : mod_->functions) {
if (func->IsInstance<relax::FunctionNode>()) {
relax::Function update_func = VisitExpr(func).as_or_throw<Function>();
builder_->UpdateFunction(gv, update_func);
}
}
ffi::Array<GlobalInfo> new_vdevices;
for (auto vdev : mod_->global_infos["vdevice"]) {
if (vdev == old_vdevice_) {
new_vdevices.push_back(new_vdevice_);
} else {
new_vdevices.push_back(vdev);
}
}
IRModule new_mod = builder_->GetContextIRModule();
new_mod->UpdateGlobalInfo("vdevice", new_vdevices);
return new_mod;
}
private:
/*! \brief Input IRModule */
IRModule mod_;
/*! \brief The new virtual device */
VDevice new_vdevice_;
/*! \brief The virtual device to be updated */
VDevice old_vdevice_;
};
namespace transform {
Pass UpdateVDevice(VDevice new_vdevice, int64_t index) {
auto pass_func = [=](IRModule m, PassContext pc) {
return relax::VDeviceMutator(m, new_vdevice, index).Run();
};
return CreateModulePass(/*pass_function=*/pass_func,
/*opt_level=*/0,
/*pass_name=*/"UpdateVDevice",
/*required=*/{});
}
TVM_FFI_STATIC_INIT_BLOCK() {
namespace refl = tvm::ffi::reflection;
refl::GlobalDef().def("relax.transform.UpdateVDevice", UpdateVDevice);
}
} // namespace transform
} // namespace relax
} // namespace tvm