Unverified Commit c2bdccfa authored by Sang Ik Lee's avatar Sang Ik Lee Committed by GitHub

[MLIR] Remove halide. (#4182)

* Remove halide.

* Remove stale code.

* Put back incorrectly removed code.
parent 8c881bc3
......@@ -640,13 +640,6 @@ if (NGRAPH_DISTRIBUTED_MLSL_ENABLE)
include(cmake/external_mlsl.cmake)
endif()
if (NGRAPH_HALIDE)
message(WARNING "Halide build system integration is currently using an older LLVM release \
and is not expected to work across most build environments. Consider \
disabling it till this message goes away")
include(cmake/external_halide.cmake)
endif()
add_subdirectory(src)
add_subdirectory(test)
......
# ******************************************************************************
# Copyright 2017-2020 Intel Corporation
#
# Licensed 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(ExternalProject)
find_package(ZLIB REQUIRED)
set(HALIDE_LLVM_TARBALL_URL https://releases.llvm.org/6.0.1/clang+llvm-6.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz)
set(HALIDE_LLVM_SHA1_HASH c7db0162fbf4cc32193b6a85f84f4abee3d107b9)
ExternalProject_Add(
ext_halide_llvm
PREFIX halide_llvm
URL ${HALIDE_LLVM_TARBALL_URL}
URL_HASH SHA1=${HALIDE_LLVM_SHA1_HASH}
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
UPDATE_COMMAND ""
EXCLUDE_FROM_ALL TRUE
)
ExternalProject_Get_Property(ext_halide_llvm SOURCE_DIR)
set(HALIDE_LLVM_DIR "${SOURCE_DIR}/lib/cmake/llvm")
set(HALIDE_GIT_REPO_URL https://github.com/halide/Halide)
set(HALIDE_GIT_TAG "ea9c863")
ExternalProject_Add(
ext_halide
PREFIX halide
DEPENDS ext_halide_llvm
GIT_REPOSITORY ${HALIDE_GIT_REPO_URL}
GIT_TAG ${HALIDE_GIT_TAG}
UPDATE_COMMAND ""
CMAKE_GENERATOR ${CMAKE_GENERATOR}
CMAKE_GENERATOR_PLATFORM ${CMAKE_GENERATOR_PLATFORM}
CMAKE_GENERATOR_TOOLSET ${CMAKE_GENERATOR_TOOLSET}
CMAKE_ARGS
${NGRAPH_FORWARD_CMAKE_ARGS}
-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
-DLLVM_DIR=${HALIDE_LLVM_DIR}
-DCMAKE_INSTALL_PREFIX=${EXTERNAL_PROJECTS_ROOT}/halide
-DHALIDE_SHARED_LIBRARY=OFF
-DWITH_APPS=OFF
-DWITH_TUTORIALS=OFF
-DWITH_TESTS=OFF
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
-DTARGET_ARM=OFF
-DTARGET_AARCH64=OFF
-DTARGET_HEXAGON=OFF
-DTARGET_METAL=OFF
-DTARGET_MIPS=OFF
-DTARGET_POWERPC=OFF
-DTARGET_PTX=OFF
-DTARGET_AMDGPU=OFF
-DTARGET_OPENCL=OFF
-DTARGET_OPENGL=OFF
-DTARGET_OPENGLCOMPUTE=OFF
-DTARGET_D3D12COMPUTE=OFF
EXCLUDE_FROM_ALL TRUE
)
# Not sure if all of these are used by Halide but we can trim it down later
# if needed
set(HALIDE_LLVM_LINK_LIBS
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMX86AsmParser${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMX86CodeGen${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMGlobalISel${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMSelectionDAG${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMAsmPrinter${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMDebugInfoCodeView${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMX86Desc${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMMCDisassembler${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMX86Info${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMX86AsmPrinter${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMX86Utils${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMMCJIT${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMLineEditor${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMInterpreter${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMExecutionEngine${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMRuntimeDyld${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMCodeGen${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMTarget${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMCoroutines${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMipo${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMInstrumentation${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMVectorize${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMScalarOpts${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMLinker${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMIRReader${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMAsmParser${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMInstCombine${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMTransformUtils${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMBitWriter${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMAnalysis${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMProfileData${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMObject${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMMCParser${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMMC${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMBitReader${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMCore${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMBinaryFormat${CMAKE_STATIC_LIBRARY_SUFFIX}
${SOURCE_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}LLVMSupport${CMAKE_STATIC_LIBRARY_SUFFIX}
)
add_library(libhalidellvm INTERFACE)
add_dependencies(libhalidellvm ext_halide_llvm)
target_include_directories(libhalidellvm SYSTEM INTERFACE ${EXTERNAL_PROJECTS_ROOT}/halide_llvm/include)
target_link_libraries(libhalidellvm INTERFACE ${HALIDE_LLVM_LINK_LIBS})
......@@ -110,7 +110,6 @@ set(SRC
op/dropout.cpp
op/gelu_backprop.cpp
op/group_conv_bias.cpp
op/halide_op.cpp
op/leaky_relu.cpp
op/lstm.cpp
op/matmul_bias.cpp
......@@ -142,16 +141,6 @@ if (NOT NGRAPH_DEX_ONLY)
)
endif()
if (NGRAPH_HALIDE)
set(SRC
${SRC}
builder/compiled_kernel.cpp
builder/halide_op.cpp
builder/halide_generators.cpp
pass/halide_subgraph_extraction.cpp
)
endif()
if (NGRAPH_MLIR_ENABLE)
set(SRC
${SRC}
......@@ -214,13 +203,6 @@ if (NGRAPH_CPU_ENABLE)
if (NGRAPH_TBB_ENABLE)
target_compile_definitions(cpu_backend PRIVATE "NGRAPH_TBB_ENABLE")
endif()
if (NGRAPH_HALIDE)
target_compile_definitions(cpu_backend PRIVATE "NGRAPH_HALIDE")
ExternalProject_Get_Property(ext_halide BINARY_DIR)
target_include_directories(cpu_backend SYSTEM PRIVATE ${BINARY_DIR}/include)
target_link_libraries(cpu_backend PRIVATE ${BINARY_DIR}/lib/libHalide.a libhalidellvm)
add_dependencies(cpu_backend ext_halide)
endif()
if(NOT NGRAPH_FAST_MATH_ENABLE)
target_compile_definitions(cpu_backend PRIVATE EIGEN_FAST_MATH=0)
......
......@@ -43,7 +43,7 @@ namespace ngraph
out_shape = broadcast->get_shape();
// TODO(jmenon): Shape transformations, rank reduction etc. needs to be general
// and not in any one builder. Move this to the Halide analysis phase.
// and not in any one builder.
// Transform output shape - ex. [4, 1, 2, 2] -> [4, 1, 4]
// if we're not broadcasting along axes 2 and 3
......
//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// Licensed 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 <Halide.h>
#include <HalideBuffer.h>
#include <functional>
#include <set>
#include <string>
#include <typeindex>
#include <typeinfo>
#include <unordered_map>
#include "ngraph/op/abs.hpp"
#include "ngraph/op/add.hpp"
#include "ngraph/op/divide.hpp"
#include "ngraph/op/maximum.hpp"
#include "ngraph/op/minimum.hpp"
#include "ngraph/op/multiply.hpp"
#include "ngraph/op/negative.hpp"
#include "ngraph/op/relu.hpp"
#include "ngraph/op/subtract.hpp"
#include "halide_generators.hpp"
#include "ngraph/runtime/cpu/cpu_builder.hpp"
#include "ngraph/runtime/cpu/op/compiled_kernel.hpp"
using namespace std;
using namespace ngraph;
#define TI(x) type_index(typeid(x))
namespace ngraph
{
namespace runtime
{
namespace cpu
{
template <>
void Builder::BUILDER_DECL(ngraph::op::CompiledKernel)
{
const ngraph::op::CompiledKernel* hs =
static_cast<const ngraph::op::CompiledKernel*>(node);
const auto& generators = ngraph::runtime::cpu::halide::get_halide_generators();
auto& halide_functions = external_function->get_halide_functions();
auto& subgraph_params = external_function->get_subgraph_params();
auto& subgraph_param_sizes = external_function->get_subgraph_param_sizes();
auto& subgraph_param_indices = external_function->get_subgraph_param_indices();
std::set<std::string> param_names;
for (const auto& op : hs->get_node_list())
{
if (!generators.count(TI(*op)))
{
throw ngraph_error("Invalid op in halide subgraph");
}
vector<Halide::Func> inputs;
for (const auto& input : op->get_inputs())
{
auto tensor_name = input.get_output().get_tensor_ptr()->get_name();
if (halide_functions.count(tensor_name))
{
inputs.emplace_back(halide_functions[tensor_name]);
}
else
{
if (param_names.count(tensor_name) == 0)
{
param_names.insert(tensor_name);
subgraph_params[tensor_name] =
Halide::ImageParam(Halide::Float(32), 1, tensor_name);
subgraph_param_sizes[tensor_name] =
shape_size(input.get_output().get_tensor_ptr()->get_shape());
subgraph_param_indices.emplace(
tensor_name, external_function->get_buffer_index(tensor_name));
inputs.emplace_back(subgraph_params[tensor_name]);
}
else
{
inputs.emplace_back(subgraph_params[tensor_name]);
}
}
}
// TODO: this needs to be extended to support multi-output ops inside a subgraph
if (op->get_outputs().size() > 1)
{
throw ngraph_error("no multi-output ops in a CompiledKernel");
}
halide_functions[op->get_output_tensor_ptr()->get_name()] =
generators.at(TI(*op))(inputs);
}
auto& functors = external_function->get_functors();
std::vector<std::tuple<size_t, size_t>> buffers_data;
std::vector<Halide::Expr> results;
auto output_nodes = hs->get_kernel_outputs();
Halide::Var x;
for (size_t i = 0; i < output_nodes.size(); i++)
{
auto result_func =
halide_functions[output_nodes.at(i)->get_output_tensor_ptr()->get_name()];
results.push_back((result_func(x) + 0));
auto out_buffer_index = external_function->get_buffer_index(out[i].get_name());
buffers_data.push_back(
std::tuple<size_t, size_t>(out_buffer_index, out[i].get_size()));
}
Halide::Func terminal_func;
terminal_func(x) = Halide::Tuple(results);
CPUKernelFunctor functor = [&, terminal_func, buffers_data, param_names](
CPURuntimeContext* ctx, CPUExecutionContext* ectx) mutable {
std::vector<Halide::Argument> halide_args;
for (auto& param : param_names)
{
Halide::Buffer<float> param_buffer(
static_cast<float*>(ctx->buffer_data[subgraph_param_indices.at(param)]),
subgraph_param_sizes.at(param));
subgraph_params[param].set(param_buffer);
}
std::vector<Halide::Buffer<>> buffers;
for (auto tuple : buffers_data)
{
buffers.push_back(Halide::Buffer<float>(
static_cast<float*>(ctx->buffer_data[std::get<0>(tuple)]),
std::get<1>(tuple)));
}
Halide::Realization r(buffers);
terminal_func.realize(r);
};
functors.emplace_back(functor);
}
}
}
}
//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// Licensed 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 "halide_generators.hpp"
#include "ngraph/op/abs.hpp"
#include "ngraph/op/add.hpp"
#include "ngraph/op/divide.hpp"
#include "ngraph/op/maximum.hpp"
#include "ngraph/op/minimum.hpp"
#include "ngraph/op/multiply.hpp"
#include "ngraph/op/negative.hpp"
#include "ngraph/op/relu.hpp"
#include "ngraph/op/reshape.hpp"
#include "ngraph/op/subtract.hpp"
using namespace ngraph;
using namespace std;
#define TI(x) std::type_index(typeid(x))
namespace ngraph
{
namespace runtime
{
namespace cpu
{
namespace halide
{
const std::unordered_map<std::type_index,
std::function<Halide::Func(std::vector<Halide::Func>)>>&
get_halide_generators()
{
const static std::unordered_map<
std::type_index,
std::function<Halide::Func(std::vector<Halide::Func>)>>
generators{{TI(ngraph::op::Add),
[](std::vector<Halide::Func> in) {
Halide::Var x;
Halide::Func func;
func(x) = in[0](x) + in[1](x);
return func;
}},
{TI(ngraph::op::Multiply),
[](std::vector<Halide::Func> in) {
Halide::Var x;
Halide::Func func;
func(x) = in[0](x) * in[1](x);
return func;
}},
{TI(ngraph::op::Negative),
[](std::vector<Halide::Func> in) {
Halide::Var x;
Halide::Func func;
func(x) = -in[0](x);
return func;
}},
{TI(ngraph::op::Abs),
[](std::vector<Halide::Func> in) {
Halide::Var x;
Halide::Func func;
func(x) = Halide::abs(in[0](x));
return func;
}},
{TI(ngraph::op::Divide),
[](std::vector<Halide::Func> in) {
Halide::Var x;
Halide::Func func;
func(x) = in[0](x) / in[1](x);
return func;
}},
{TI(ngraph::op::Maximum),
[](std::vector<Halide::Func> in) {
Halide::Var x;
Halide::Func func;
func(x) = Halide::max(in[0](x), 0);
return func;
}},
{TI(ngraph::op::Minimum),
[](std::vector<Halide::Func> in) {
Halide::Var x;
Halide::Func func;
func(x) = Halide::min(in[0](x), 0);
return func;
}},
{TI(ngraph::op::Relu), [](std::vector<Halide::Func> in) {
Halide::Var x;
Halide::Func func;
func(x) = Halide::max(in[0](x), 0);
return func;
}}};
return generators;
}
}
}
}
}
//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// Licensed 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.
//*****************************************************************************
#pragma once
#include <Halide.h>
#include <HalideBuffer.h>
#include <functional>
#include <memory>
#include <typeindex>
#include <typeinfo>
#include <unordered_map>
#include <vector>
#include "ngraph/node.hpp"
namespace ngraph
{
namespace runtime
{
namespace cpu
{
namespace halide
{
const std::unordered_map<std::type_index,
std::function<Halide::Func(std::vector<Halide::Func>)>>&
get_halide_generators();
}
}
}
}
//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// Licensed 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 <Halide.h>
#include <HalideBuffer.h>
#include <functional>
#include <string>
#include <typeindex>
#include <typeinfo>
#include <unordered_map>
#include "ngraph/op/add.hpp"
#include "ngraph/op/multiply.hpp"
#include "ngraph/op/relu.hpp"
#include "halide_generators.hpp"
#include "ngraph/runtime/cpu/cpu_builder.hpp"
#include "ngraph/runtime/cpu/op/halide_op.hpp"
using namespace std;
using namespace ngraph;
#define TI(x) type_index(typeid(x))
namespace ngraph
{
namespace runtime
{
namespace cpu
{
template <>
void Builder::BUILDER_DECL(ngraph::runtime::cpu::op::HalideOp)
{
const ngraph::runtime::cpu::op::HalideOp* hs =
static_cast<const ngraph::runtime::cpu::op::HalideOp*>(node);
const auto& generators = ngraph::runtime::cpu::halide::get_halide_generators();
auto& halide_functions = external_function->get_halide_functions();
auto& subgraph_params = external_function->get_subgraph_params();
auto& subgraph_param_sizes = external_function->get_subgraph_param_sizes();
auto& subgraph_param_indices = external_function->get_subgraph_param_indices();
for (const auto& op : hs->get_ops())
{
if (!generators.count(TI(*op)))
{
throw ngraph_error("Invalid op in halide subgraph");
}
vector<Halide::Func> inputs;
for (const auto& input : op->get_inputs())
{
auto tensor_name = input.get_output().get_tensor_ptr()->get_name();
if (halide_functions.count(tensor_name))
{
inputs.emplace_back(halide_functions[tensor_name]);
}
else
{
subgraph_params[tensor_name] = Halide::ImageParam(Halide::Float(32), 1);
subgraph_param_sizes[tensor_name] =
shape_size(input.get_output().get_tensor_ptr()->get_shape());
subgraph_param_indices.emplace(
tensor_name, external_function->get_buffer_index(tensor_name));
inputs.emplace_back(subgraph_params[tensor_name]);
}
}
halide_functions[op->get_output_tensor_ptr()->get_name()] =
generators.at(TI(*op))(inputs);
}
auto out_tensor_name = hs->get_ops().back()->get_output_tensor_ptr()->get_name();
auto& functors = external_function->get_functors();
auto out_buffer_index = external_function->get_buffer_index(out[0].get_name());
auto& terminal_func = halide_functions[out_tensor_name];
auto out_size = out[0].get_size();
auto functor = [&, out_size, out_buffer_index](CPURuntimeContext* ctx,
CPUExecutionContext* ectx) {
for (auto& param : subgraph_params)
{
Halide::Buffer<float> param_buffer(
static_cast<float*>(
ctx->buffer_data[subgraph_param_indices.at(param.first)]),
subgraph_param_sizes.at(param.first));
param.second.set(param_buffer);
}
Halide::Buffer<float> out_buffer(
static_cast<float*>(ctx->buffer_data[out_buffer_index]), out_size);
terminal_func.realize(out_buffer);
};
functors.emplace_back(functor);
}
}
}
}
......@@ -111,7 +111,6 @@
#include "ngraph/runtime/cpu/kernel/tanh.hpp"
#include "ngraph/runtime/cpu/kernel/xor.hpp"
#include "ngraph/runtime/cpu/op/convert_layout.hpp"
#include "ngraph/runtime/cpu/op/halide_op.hpp"
#include "ngraph/type/element_type.hpp"
#include "ngraph/util.hpp"
......@@ -680,9 +679,7 @@ namespace ngraph
static BuildOpMap build_dispatcher{
{TI(ngraph::op::Parameter), &runtime::cpu::Builder::nop},
{TI(ngraph::op::CompiledKernel),
&runtime::cpu::Builder::build<ngraph::op::CompiledKernel>},
{TI(ngraph::runtime::cpu::op::HalideOp),
&runtime::cpu::Builder::build<ngraph::runtime::cpu::op::HalideOp>}};
&runtime::cpu::Builder::build<ngraph::op::CompiledKernel>}};
return build_dispatcher;
}
......
......@@ -206,7 +206,6 @@
#include "ngraph/runtime/cpu/pass/cpu_post_layout_optimizations.hpp"
#include "ngraph/runtime/cpu/pass/cpu_rnn_fusion.hpp"
#include "ngraph/runtime/cpu/pass/cpu_workspace_insertion.hpp"
#include "ngraph/runtime/cpu/pass/halide_subgraph_extraction.hpp"
using namespace std;
using namespace ngraph;
......@@ -1302,9 +1301,6 @@ void runtime::cpu::CPU_ExternalFunction::register_common_passes(
REGISTER_KNOBBED_PASS(CPUQuantFusion, true, runtime::cpu::pass)
REGISTER_KNOBBED_PASS(CPUHorizontalFusion, true, runtime::cpu::pass)
REGISTER_KNOBBED_PASS(CPUCollapseDims, true, runtime::cpu::pass)
#if defined(NGRAPH_HALIDE)
REGISTER_KNOBBED_PASS(HalideSubgraphExtraction, true, ngraph::runtime::cpu::pass)
#endif
#ifdef NGRAPH_MLIR_ENABLE
if (std::getenv("NGRAPH_MLIR") != nullptr)
......
......@@ -27,10 +27,6 @@
#include <utility>
#include <vector>
#if defined(NGRAPH_HALIDE)
#include <Halide.h>
#endif
#if !defined(NGRAPH_DEX_ONLY)
#include "ngraph/code_writer.hpp"
......@@ -184,25 +180,6 @@ namespace ngraph
const std::vector<PerformanceCounter>& get_perf_counters();
#if defined(NGRAPH_HALIDE)
std::unordered_map<std::string, Halide::Func>& get_halide_functions()
{
return halide_functions;
}
std::unordered_map<std::string, Halide::ImageParam>& get_subgraph_params()
{
return subgraph_params;
}
std::unordered_map<std::string, int>& get_subgraph_param_sizes()
{
return subgraph_param_sizes;
}
std::unordered_map<std::string, size_t>> &get_subgraph_param_indices()
{
return subgraph_param_indices;
}
#endif
protected:
void build(ngraph::pass::PassConfig& pass_config);
......@@ -344,13 +321,6 @@ namespace ngraph
bool m_is_built;
std::vector<runtime::PerformanceCounter> m_perf_counters;
#if defined(NGRAPH_HALIDE)
std::unordered_map<std::string, Halide::Func> halide_functions;
std::unordered_map<std::string, Halide::ImageParam> subgraph_params;
std::unordered_map<std::string, int> subgraph_param_sizes;
std::unordered_map<std::string, size_t> subgraph_param_indices;
#endif
/// Map each node with mkldnn implementation to its mkldnn primitive creating
/// string, deps, mkldnn primitive index, and mkldnn scratchpad size.
std::map<const Node*, std::tuple<std::string, std::vector<size_t>, size_t, size_t>>
......
//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// Licensed 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 "ngraph/runtime/cpu/op/halide_op.hpp"
using namespace std;
using namespace ngraph;
shared_ptr<Node> runtime::cpu::op::HalideOp::copy_with_new_args(const NodeVector& new_args) const
{
return make_shared<HalideOp>(as_output_vector(new_args), m_ops, m_output_type, m_output_shape);
}
constexpr NodeTypeInfo runtime::cpu::op::HalideOp::type_info;
runtime::cpu::op::HalideOp::HalideOp(const OutputVector& args,
const std::list<Output<Node>>& ops,
const element::Type& out_type,
const Shape& out_shape)
: Op(args)
, m_ops(ops)
, m_output_type(out_type)
, m_output_shape(out_shape)
{
constructor_validate_and_infer_types();
}
void runtime::cpu::op::HalideOp::validate_and_infer_types()
{
set_output_type(0, m_output_type, m_output_shape);
}
//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// Licensed 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.
//*****************************************************************************
#pragma once
#include <list>
#include <vector>
#include "ngraph/op/op.hpp"
#include "ngraph/runtime/cpu/cpu_backend_visibility.h"
namespace ngraph
{
namespace runtime
{
namespace cpu
{
namespace op
{
class HalideOp : public ngraph::op::Op
{
public:
CPU_BACKEND_API
static constexpr NodeTypeInfo type_info{"HalideOp", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
HalideOp(const OutputVector& args,
const std::list<Output<Node>>& ops,
const element::Type& out_type,
const Shape& out_shape);
virtual void validate_and_infer_types() override;
virtual std::shared_ptr<Node>
copy_with_new_args(const NodeVector& new_args) const override;
const std::list<Output<Node>>& get_ops() const { return m_ops; }
private:
std::list<Output<Node>> m_ops;
element::Type m_output_type;
Shape m_output_shape;
};
}
}
}
}
//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// Licensed 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 <iostream>
#include <list>
#include <typeindex>
#include <typeinfo>
#include <unordered_set>
#include "ngraph/op/add.hpp"
#include "ngraph/op/multiply.hpp"
#include "ngraph/op/relu.hpp"
#include "ngraph/runtime/cpu/op/halide_op.hpp"
#include "ngraph/runtime/cpu/pass/halide_subgraph_extraction.hpp"
using namespace std;
using namespace ngraph;
#define TI(x) type_index(typeid(x))
namespace ngraph
{
namespace runtime
{
namespace cpu
{
namespace halide
{
static const std::unordered_set<std::type_index> whitelist{
TI(ngraph::op::Add), TI(ngraph::op::Multiply), TI(ngraph::op::Relu)};
static const std::unordered_set<std::type_index> skiplist{TI(ngraph::op::Parameter),
TI(ngraph::op::Result)};
}
}
}
}
// Support for multiple results, multiple outputs and getoutputelement, and multiple subgraphs in a
// single pipeline is not implemented since this should go away in favor of the "hybrid" transformer
// approach of carving out subgraphs in core ngraph
bool runtime::cpu::pass::HalideSubgraphExtraction::run_on_function(
std::shared_ptr<ngraph::Function> function)
{
list<shared_ptr<Node>> worklist;
auto results = function->get_results();
// Artificial limitation
if (results.size() > 1)
{
return false;
}
if (function->get_result()->get_element_type() != element::f32)
{
return false;
}
for (const auto& result : results)
{
worklist.emplace_back(result);
}
unordered_set<shared_ptr<Node>> ops;
list<shared_ptr<Node>> ordered_ops;
while (!worklist.empty())
{
const auto& node = worklist.front();
if (!halide::skiplist.count(TI(*node)))
{
if (halide::whitelist.count(TI(*node)))
{
ops.emplace(node);
ordered_ops.emplace_back(node);
}
else
{
break;
}
}
const auto& args = node->get_arguments();
for (const auto& arg : args)
{
worklist.emplace_back(arg);
}
worklist.pop_front();
}
NodeVector liveins;
for (const auto& op : ops)
{
const auto& args = op->get_arguments();
for (const auto& arg : args)
{
if (!ops.count(arg))
{
liveins.emplace_back(arg);
}
}
}
ordered_ops.reverse();
if (ordered_ops.size() > 1)
{
auto subgraph = make_shared<cpu::op::HalideOp>(liveins,
ordered_ops,
function->get_result()->get_element_type(),
function->get_result()->get_shape());
replace_node(function->get_result()->get_argument(0), subgraph);
return true;
}
else
{
return false;
}
}
//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// Licensed 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.
//*****************************************************************************
#pragma once
#include "ngraph/pass/pass.hpp"
#include "ngraph/runtime/cpu/cpu_external_function.hpp"
namespace ngraph
{
namespace runtime
{
namespace cpu
{
namespace pass
{
class HalideSubgraphExtraction : public ngraph::pass::FunctionPass
{
public:
HalideSubgraphExtraction() {}
bool run_on_function(std::shared_ptr<ngraph::Function> function) override;
};
}
}
}
}
......@@ -236,9 +236,6 @@ else()
if (NOT NGRAPH_DEX_ONLY)
list(APPEND SRC cpu_codegen.cpp)
endif()
if (NGRAPH_HALIDE)
list(APPEND SRC halide.cpp)
endif()
set(ACTIVE_BACKEND_LIST ${ACTIVE_BACKEND_LIST} CPU)
endif()
......@@ -589,10 +586,6 @@ if (NGRAPH_TBB_ENABLE)
target_compile_definitions(unit-test PRIVATE "NGRAPH_TBB_ENABLE")
endif()
if (NGRAPH_HALIDE)
target_compile_definitions(unit-test PRIVATE "NGRAPH_HALIDE")
endif()
if (NGRAPH_INTERPRETER_ENABLE)
target_compile_definitions(unit-test PRIVATE NGRAPH_INTERPRETER_ENABLE)
target_link_libraries(unit-test PRIVATE interpreter_backend)
......
......@@ -120,7 +120,6 @@ TEST(cpu_test, trivial_in_place_relu)
add->output(0).get_tensor().get_pool_offset());
}
#ifndef NGRAPH_HALIDE
TEST(cpu_test, MLIR_DISABLE_TEST(trivial_in_place_relu_fail))
{
auto A = make_shared<op::Parameter>(element::f32, Shape{16, 1});
......@@ -134,7 +133,6 @@ TEST(cpu_test, MLIR_DISABLE_TEST(trivial_in_place_relu_fail))
ASSERT_NE(relu->output(0).get_tensor().get_pool_offset(),
add->output(0).get_tensor().get_pool_offset());
}
#endif
#ifdef NGRAPH_TBB_ENABLE
TEST(cpu_test, abc_tbb)
......
//*****************************************************************************
// Copyright 2017-2020 Intel Corporation
//
// Licensed 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 <algorithm>
#include <cstdio>
#include <iostream>
#include <list>
#include <memory>
#include "gtest/gtest.h"
#include "ngraph/ngraph.hpp"
#include "ngraph/util.hpp"
#include "util/all_close.hpp"
#include "util/test_tools.hpp"
using namespace ngraph;
using namespace std;
TEST(halide, halide_subgraph)
{
Shape shape{8};
auto A = make_shared<op::Parameter>(element::f32, shape);
auto B = make_shared<op::Parameter>(element::f32, shape);
auto C = make_shared<op::Parameter>(element::f32, shape);
auto D = make_shared<op::Parameter>(element::f32, shape);
auto relu = make_shared<op::Relu>((A + B) * C);
auto f = make_shared<Function>(relu + D, ParameterVector{A, B, C, D});
auto backend = runtime::Backend::create("CPU");
shared_ptr<runtime::Tensor> a = backend->create_tensor(element::f32, shape);
shared_ptr<runtime::Tensor> b = backend->create_tensor(element::f32, shape);
shared_ptr<runtime::Tensor> c = backend->create_tensor(element::f32, shape);
shared_ptr<runtime::Tensor> d = backend->create_tensor(element::f32, shape);
shared_ptr<runtime::Tensor> result = backend->create_tensor(element::f32, shape);
vector<float> data{-1, 4, -2, 5, 1, 5, 7, 9};
copy_data(a, data);
copy_data(b, data);
copy_data(c, data);
copy_data(d, data);
vector<float> expected{1, 36, 6, 55, 3, 55, 105, 171};
auto handle = backend->compile(f);
handle->call_with_validate({result}, {a, b, c, d});
EXPECT_TRUE(test::all_close(read_vector<float>(result), expected, 1.0e-4f, 1.0e-4f));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment