"src/targets/vscode:/vscode.git/clone" did not exist on "6f032fc0841f60b5c02b64e7a10ea367507c5c8a"
Commit 8143e4fb authored by wsttiger's avatar wsttiger
Browse files

Merge branch 'master' into remove_concat

parents 0a4583b7 9ca0fbf1
......@@ -4,6 +4,12 @@ if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
message(FATAL_ERROR "The binary and source directroy cannot be the same")
endif()
# This has to be initialized before the project() command appears
# Set the default of CMAKE_BUILD_TYPE to be release, unless user specifies with -D. MSVC_IDE does not use CMAKE_BUILD_TYPE
if( NOT MSVC_IDE AND NOT CMAKE_BUILD_TYPE )
set( CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." )
endif()
project(migraphlib)
find_package(ROCM REQUIRED)
......
......@@ -2,8 +2,5 @@ pfultz2/rocm-recipes
pcre
danmar/cppcheck@f965e5873 -DHAVE_RULES=1
ROCm-Developer-Tools/HIP@3a41f286203968421c557338d6fb39c36f3c717c
# Needed for clang-ocl
RadeonOpenCompute/rocm-cmake@6240bb3 --build
RadeonOpenCompute/clang-ocl@799713643b5591a3b877c586ef2c7fbc012af819
# python/cpython@v3.6.6 -X autotools -H sha256:92aa914572c695c0aeb01b0a214813f414da4b51a371234df514a74761f2bb36
-f requirements.txt
......@@ -14,5 +14,5 @@ gpu::target
cpu::target
-----------
.. doxygenstruct:: migraph::cpu::cpu_target
.. doxygenstruct:: migraph::cpu::target
......@@ -21,6 +21,9 @@ add_library(migraph
rocm_clang_tidy_check(migraph)
target_include_directories(migraph PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
find_path(HALF_INCLUDE_DIR half.hpp)
target_include_directories(migraph SYSTEM PUBLIC ${HALF_INCLUDE_DIR})
add_subdirectory(onnx)
add_subdirectory(targets/cpu)
if(MIGRAPH_ENABLE_GPU)
......
......@@ -3,9 +3,30 @@
#include <migraph/instruction.hpp>
#include <migraph/iterator_for.hpp>
#include <migraph/functional.hpp>
#include <migraph/ranges.hpp>
namespace migraph {
template <class Range, class Iterator>
std::ptrdiff_t bidistance(const Range& r, Iterator start, Iterator last)
{
auto start_forward = start;
auto start_backwards = start;
std::size_t n = 0;
while(start_forward != last and start_backwards != last)
{
n++;
if(start_forward != r.end())
start_forward++;
if(start_backwards != r.begin())
start_backwards--;
}
if(start_forward == last)
return n;
else
return -n;
}
void dead_code_elimination::apply(program& p) const
{
auto last = std::prev(p.end());
......@@ -16,18 +37,21 @@ void dead_code_elimination::apply(program& p) const
if(ins == p.begin())
continue;
const auto i = std::prev(ins);
// Skip instruction with empty shape as output unless its a builtin
if(i->get_shape().elements() == 0 and not(i->name().front() == '@'))
continue;
// Skip the last instruction
if(i == last)
break;
// Skip instruction with empty shape as output unless its a builtin
if(i->get_shape().elements() == 0 and not(i->name().front() == '@'))
continue;
assert(bidistance(p, i, last) > 0);
fix([&](auto self, auto leaf) {
assert(p.has_instruction(leaf));
if(leaf->outputs().empty())
{
auto args = leaf->inputs();
leaf->clear_arguments();
assert(bidistance(p, last, leaf) < 0);
assert(leaf != ins);
p.move_instruction(leaf, p.end());
for(auto arg : args)
self(arg);
......
......@@ -3,23 +3,24 @@
#include <migraph/argument.hpp>
#include <migraph/literal.hpp>
#include <migraph/type_traits.hpp>
#include <random>
namespace migraph {
template <class T, MIGRAPH_REQUIRES(std::is_floating_point<T>{})>
template <class T, MIGRAPH_REQUIRES(is_floating_point<T>{})>
constexpr T normalize(unsigned long z)
{
if(z == 0)
return 0;
return T(0);
const auto max = 32;
const double range = max / 2; // NOLINT
double result = (z % max) / range;
result -= 1;
return result;
return T(result);
}
template <class T, MIGRAPH_REQUIRES(std::is_signed<T>{} and not std::is_floating_point<T>{})>
template <class T, MIGRAPH_REQUIRES(is_signed<T>{} and not is_floating_point<T>{})>
constexpr T normalize(unsigned long z)
{
const auto max = std::numeric_limits<T>::max();
......@@ -27,7 +28,7 @@ constexpr T normalize(unsigned long z)
return half_max - (z % max);
}
template <class T, MIGRAPH_REQUIRES(not std::is_signed<T>{} and std::is_integral<T>{})>
template <class T, MIGRAPH_REQUIRES(not is_signed<T>{} and std::is_integral<T>{})>
constexpr T normalize(unsigned long z)
{
const auto max = std::numeric_limits<T>::max();
......
/*=============================================================================
Copyright (c) 2017 Paul Fultz II
half.hpp
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/
#ifndef MIGRAPH_GUARD_RTGLIB_HALF_HPP
#define MIGRAPH_GUARD_RTGLIB_HALF_HPP
#include <half.hpp>
namespace migraph {
using half = half_float::half;
namespace detail {
template <class T>
struct deduce
{
using type = T;
};
template <>
struct deduce<half_float::detail::expr>
{
using type = half;
};
} // namespace detail
template <class T>
using deduce = typename detail::deduce<T>::type;
} // namespace migraph
#endif
......@@ -20,10 +20,10 @@ struct literal : raw_data<literal>
{
literal() {}
template <class T>
literal(T x) : buffer(make_shared_array<char>(sizeof(T))), m_shape(shape::get_type<T>{})
template <class U, class T = deduce<U>>
literal(U x) : buffer(make_shared_array<char>(sizeof(T))), m_shape(shape::get_type<T>{})
{
static_assert(std::is_trivial<T>{}, "Literals can only be trivial types");
static_assert(std::is_trivially_copyable<T>{}, "Literals can only be trivial types");
*(reinterpret_cast<T*>(buffer.get())) = x;
}
......@@ -31,7 +31,7 @@ struct literal : raw_data<literal>
literal(const shape& s, const std::vector<T>& x)
: buffer(make_shared_array<char>(s.bytes())), m_shape(s)
{
static_assert(std::is_trivial<T>{}, "Literals can only be trivial types");
static_assert(std::is_trivially_copyable<T>{}, "Literals can only be trivial types");
fill(x.begin(), x.end());
}
......@@ -39,7 +39,7 @@ struct literal : raw_data<literal>
literal(const shape& s, const std::initializer_list<T>& x)
: buffer(make_shared_array<char>(s.bytes())), m_shape(s)
{
static_assert(std::is_trivial<T>{}, "Literals can only be trivial types");
static_assert(std::is_trivially_copyable<T>{}, "Literals can only be trivial types");
fill(x.begin(), x.end());
}
......@@ -101,7 +101,7 @@ literal transform(literal l, F f)
literal result;
l.visit([&](auto x) {
using type = std::remove_cv_t<typename decltype(x)::value_type>;
std::vector<type> output(x.size(), 0.0);
std::vector<type> output(x.size(), type(0));
std::transform(x.begin(), x.end(), output.begin(), f);
result = literal{l.get_shape(), output};
});
......@@ -115,7 +115,7 @@ literal transform(literal l1, literal l2, F f)
literal result;
visit_all(l1, l2)([&](auto x, auto y) {
using type = std::remove_cv_t<typename decltype(x)::value_type>;
std::vector<type> output(x.size(), 0.0);
std::vector<type> output(x.size(), type(0));
std::transform(x.begin(), x.end(), y.begin(), output.begin(), f);
result = literal{l1.get_shape(), output};
});
......
......@@ -256,7 +256,6 @@ struct operation
shape compute_shape(const std::vector<shape>& input) const override
{
return private_detail_te_value.compute_shape(input);
}
......
......@@ -306,10 +306,6 @@ struct contiguous
check_shapes{inputs, *this}.has(1);
auto lens = inputs.at(0).lens();
auto t = inputs.at(0).type();
if(lens.size() < 2)
{
MIGRAPH_THROW("Number of dimensions should exceed 1");
}
return {t, lens};
}
};
......@@ -582,7 +578,7 @@ struct reshape
}
};
struct gemm
struct dot
{
float alpha = 1.0;
float beta = 0.0;
......@@ -593,7 +589,7 @@ struct gemm
return pack(f(self.alpha, "alpha"), f(self.beta, "beta"));
}
std::string name() const { return "gemm"; }
std::string name() const { return "dot"; }
shape compute_shape(std::vector<shape> inputs) const
{
check_shapes{inputs, *this}.has(2).same_type();
......@@ -766,6 +762,27 @@ struct broadcast
}
};
struct scalar
{
shape scalar_bcast;
std::string name() const { return "scalar"; }
shape compute_shape(std::vector<shape> inputs) const
{
assert(check_shapes{inputs}.has(1).only_dims(1).size() == 1);
auto t = inputs.at(0).type();
auto input = inputs.at(0);
std::vector<std::size_t> strides(scalar_bcast.lens().size(), 0);
return {t, scalar_bcast.lens(), strides};
}
argument compute(context&, shape output_shape, std::vector<argument> args) const
{
return {std::move(output_shape), std::move(args.at(0).data)};
}
};
struct binary
{
shape compute_shape(std::vector<shape> inputs) const
......
......@@ -45,6 +45,12 @@ bool contains(const C& c, const T& x)
return generic_find(c, x) != c.end();
}
template <class T>
bool contains(const std::initializer_list<T>& c, const T& x)
{
return generic_find(c, x) != c.end();
}
template <class T, class U>
bool contains(const std::initializer_list<T>& c, const U& x)
{
......
......@@ -8,6 +8,7 @@
#include <memory>
#include <migraph/errors.hpp>
#include <migraph/half.hpp>
namespace migraph {
......@@ -19,6 +20,7 @@ struct shape
// Add new types here
// clang-format off
#define MIGRAPH_SHAPE_VISIT_TYPES(m) \
m(half_type, half) \
m(float_type, float) \
m(double_type, double) \
m(uint8_type, uint8_t) \
......@@ -92,6 +94,8 @@ struct shape
/// Returns true if the shape is in its standard format. That is, the shape is both packed and
/// not transposed.
bool standard() const;
/// Returns true if all strides are equal to 0 (scalar tensor)
bool scalar() const;
friend bool operator==(const shape& x, const shape& y);
friend bool operator!=(const shape& x, const shape& y);
......
/*=============================================================================
Copyright (c) 2017 Paul Fultz II
type_traits.hpp
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/
#ifndef MIGRAPH_GUARD_RTGLIB_TYPE_TRAITS_HPP
#define MIGRAPH_GUARD_RTGLIB_TYPE_TRAITS_HPP
#include <type_traits>
#include <migraph/half.hpp>
namespace migraph {
#define MIGRAPH_DETAIL_EXTEND_TRAIT_FOR(trait, T) \
template <class X> \
struct trait : std::trait<X> \
{ \
}; \
\
template <> \
struct trait<T> : std::true_type \
{ \
};
MIGRAPH_DETAIL_EXTEND_TRAIT_FOR(is_floating_point, half)
MIGRAPH_DETAIL_EXTEND_TRAIT_FOR(is_signed, half)
MIGRAPH_DETAIL_EXTEND_TRAIT_FOR(is_arithmetic, half)
} // namespace migraph
#endif
......@@ -6,7 +6,7 @@
#include <migraph/onnx.hpp>
#include <migraph/cpu/cpu_target.hpp>
#include <migraph/cpu/target.hpp>
#include <migraph/gpu/target.hpp>
#include <migraph/gpu/hip.hpp>
#include <migraph/generate.hpp>
......@@ -86,7 +86,7 @@ int main(int argc, char const* argv[])
else
{
// CPU target
prog.compile(migraph::cpu::cpu_target{});
prog.compile(migraph::cpu::target{});
auto s = migraph::shape{migraph::shape::float_type, {1, 3, 32, 32}};
auto labels = imageset.first;
auto input = imageset.second;
......
......@@ -50,17 +50,20 @@ struct onnx_parser
{
add_generic_op("Add", op::add{});
add_generic_op("Div", op::div{});
add_generic_op("MatMul", op::gemm{});
add_generic_op("MatMul", op::dot{});
add_generic_op("Mul", op::mul{});
add_generic_op("Relu", op::activation{"relu"});
add_generic_op("Sub", op::sub{});
add_generic_op("Sum", op::add{});
add_mem_op("ImageScaler", &onnx_parser::parse_imagescaler);
add_mem_op("LeakyRelu", &onnx_parser::parse_leaky_relu);
add_mem_op("Constant", &onnx_parser::parse_constant);
add_mem_op("Conv", &onnx_parser::parse_conv);
add_mem_op("MaxPool", &onnx_parser::parse_pooling);
add_mem_op("AveragePool", &onnx_parser::parse_pooling);
add_mem_op("GlobalMaxPool", &onnx_parser::parse_pooling);
add_mem_op("GlobalAveragePool", &onnx_parser::parse_pooling);
add_mem_op("Reshape", &onnx_parser::parse_reshape);
add_mem_op("Flatten", &onnx_parser::parse_flatten);
add_mem_op("Gemm", &onnx_parser::parse_gemm);
......@@ -147,7 +150,12 @@ struct onnx_parser
attribute_map attributes,
std::vector<instruction_ref> args)
{
op::pooling op{name == "MaxPool" ? "max" : "average"};
op::pooling op{ends_with(name, "MaxPool") ? "max" : "average"};
if(starts_with(name, "Global"))
{
auto lens = args.front()->get_shape().lens();
op.lengths = {lens[2], lens[3]};
}
if(contains(attributes, "pads"))
{
copy(attributes["pads"].ints(), op.padding.begin());
......@@ -274,11 +282,11 @@ struct onnx_parser
if(args.size() == 3)
{
uint64_t axis = 1;
auto l3 = prog.add_instruction(op::gemm{alpha, beta}, l1, l2);
auto l3 = prog.add_instruction(op::dot{alpha, beta}, l1, l2);
auto l4 = prog.add_instruction(op::broadcast{axis, l3->get_shape()}, args[2]);
return prog.add_instruction(op::add{}, l3, l4);
}
return prog.add_instruction(op::gemm{alpha, beta}, l1, l2);
return prog.add_instruction(op::dot{alpha, beta}, l1, l2);
}
instruction_ref
......@@ -315,7 +323,7 @@ struct onnx_parser
attribute_map attributes,
std::vector<instruction_ref> args)
{
float alpha = 0.01;
float alpha = 0.01; // default alpha val for leaky relu
if(contains(attributes, "alpha"))
{
alpha = parse_value(attributes.at("alpha")).at<float>();
......@@ -324,6 +332,34 @@ struct onnx_parser
return prog.add_instruction(op, args.front());
}
instruction_ref parse_imagescaler(const std::string&,
attribute_map attributes,
std::vector<instruction_ref> args)
{
float scale = 1.0;
std::vector<float> bias{};
if(contains(attributes, "scale"))
{
scale = parse_value(attributes.at("scale")).at<float>();
}
if(contains(attributes, "bias"))
{
auto&& bias_floats = attributes["bias"].floats();
bias = std::vector<float>(bias_floats.begin(), bias_floats.end());
}
auto input_shape = args.front()->get_shape();
auto scale_val = prog.add_literal(scale);
auto bias_vals = prog.add_literal(
migraph::literal{migraph::shape{migraph::shape::float_type, {bias.size()}}, bias});
auto scale_tensor = prog.add_instruction(migraph::op::scalar{input_shape}, scale_val);
auto img_scaled = prog.add_instruction(migraph::op::mul{}, args.front(), scale_tensor);
auto bias_bcast = prog.add_instruction(migraph::op::broadcast{1, input_shape}, bias_vals);
return prog.add_instruction(migraph::op::add{}, img_scaled, bias_bcast);
}
void parse_from(std::istream& is)
{
onnx::ModelProto model;
......@@ -555,10 +591,15 @@ struct onnx_parser
}
std::vector<std::size_t> dims;
auto&& tensor_dims = t.tensor_type().shape().dim();
std::transform(tensor_dims.begin(),
tensor_dims.end(),
std::back_inserter(dims),
[](auto&& d) { return d.dim_value(); });
std::transform(
tensor_dims.begin(), tensor_dims.end(), std::back_inserter(dims), [](auto&& d) {
if(not d.has_dim_value())
{
long default_batch_size = 1; // FIXME
return default_batch_size;
}
return d.dim_value();
});
return {shape_type, dims};
}
};
......
#include <migraph/onnx.hpp>
#include <migraph/cpu/cpu_target.hpp>
#include <migraph/cpu/target.hpp>
#include <migraph/gpu/target.hpp>
#include <migraph/gpu/hip.hpp>
#include <migraph/generate.hpp>
......@@ -18,7 +18,7 @@ template <class F>
migraph::argument run_cpu(F f)
{
auto p = f();
p.compile(migraph::cpu::cpu_target{});
p.compile(migraph::cpu::target{});
migraph::program::parameter_map m;
for(auto&& x : p.get_parameter_shapes())
{
......
......@@ -196,6 +196,7 @@ void memory_coloring_impl::register_operand_alias()
operand_alias["identity"] = 0;
operand_alias["reshape"] = 0;
operand_alias["pass"] = 0;
operand_alias["scalar"] = 0;
}
void memory_coloring_impl::rewrite()
......
......@@ -427,7 +427,7 @@ void program::perf_report(std::ostream& os, std::size_t n, parameter_map params)
}
double total_time = common_average(total_vec);
double rate = std::ceil(1000.0 / total_time);
double rate = 1000.0 / total_time;
double overhead_time = common_average(overhead_vec);
double overhead_percent = overhead_time * 100.0 / total_time;
double total_instruction_time = 0.0;
......
......@@ -29,8 +29,8 @@ struct shape_impl
: m_type(t), m_lens(std::move(l)), m_strides(std::move(s))
{
assert(m_lens.size() == m_strides.size());
assert(std::any_of(m_strides.begin(), m_strides.end(), [](auto x) { return x > 0; }) and
"At least one stride must be non-zero");
// assert(std::any_of(m_strides.begin(), m_strides.end(), [](auto x) { return x > 0; }) and
// "At least one stride must be non-zero");
m_standard = this->elements() == this->element_space() and
std::is_sorted(m_strides.rbegin(), m_strides.rend());
}
......@@ -153,6 +153,13 @@ bool shape::broadcasted() const
std::multiplies<std::size_t>()) == 0;
}
bool shape::scalar() const
{
assert(this->lens().size() == this->strides().size());
// if any stride > 0, then accumulate will return false
return std::accumulate(this->strides().begin(), this->strides().end(), std::size_t(0)) == 0;
}
bool shape::standard() const { return impl->m_standard; }
std::size_t shape::element_space() const { return impl->element_space(); }
......
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