Commit 4332ccf6 authored by Paul's avatar Paul
Browse files

Refactor

parent 9b5e0c18
...@@ -18,10 +18,8 @@ ...@@ -18,10 +18,8 @@
#include <migraphx/rewrite_rnn.hpp> #include <migraphx/rewrite_rnn.hpp>
#include <migraphx/eliminate_concat.hpp> #include <migraphx/eliminate_concat.hpp>
#include <migraphx/gpu/concat_gpu_opt.hpp> #include <migraphx/gpu/concat_gpu_opt.hpp>
#include <migraphx/pre_scheduling.hpp> #include <migraphx/gpu/schedule_model.hpp>
#include <migraphx/gpu/machine_model.hpp> #include <migraphx/schedule.hpp>
#include <migraphx/gpu/find_concur_gpu.hpp>
#include <migraphx/gpu/insert_instruction_gpu.hpp>
namespace migraphx { namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS { inline namespace MIGRAPHX_INLINE_NS {
...@@ -30,8 +28,6 @@ namespace gpu { ...@@ -30,8 +28,6 @@ namespace gpu {
std::vector<pass> target::get_passes(migraphx::context& gctx) const std::vector<pass> target::get_passes(migraphx::context& gctx) const
{ {
auto& ctx = any_cast<context>(gctx); auto& ctx = any_cast<context>(gctx);
std::function<std::pair<int, int>(const operation&)> weight_func = op_info();
int num_of_streams = ctx.get_current_device().nstreams();
// clang-format off // clang-format off
return return
{ {
...@@ -57,8 +53,9 @@ std::vector<pass> target::get_passes(migraphx::context& gctx) const ...@@ -57,8 +53,9 @@ std::vector<pass> target::get_passes(migraphx::context& gctx) const
fuse_ops{&ctx}, fuse_ops{&ctx},
dead_code_elimination{}, dead_code_elimination{},
write_literals{&ctx}, write_literals{&ctx},
pre_scheduling{weight_func, num_of_streams, insert_instruction_gpu{}}, schedule{gpu::schedule_model{ctx.get_current_device().nstreams()}},
memory_coloring{"hip::allocate", num_of_streams, find_concur_gpu{}}, memory_coloring{"hip::allocate"},
dead_code_elimination{},
eliminate_workspace{}, eliminate_workspace{},
eliminate_allocation{"hip::allocate"}, eliminate_allocation{"hip::allocate"},
check_context<context>{}, check_context<context>{},
......
...@@ -130,9 +130,7 @@ migraphx::argument run_gpu(migraphx::program& p) ...@@ -130,9 +130,7 @@ migraphx::argument run_gpu(migraphx::program& p)
EXPECT(is_shared(ctx, p.get_context())); EXPECT(is_shared(ctx, p.get_context()));
p.dry_run(m); p.dry_run(m);
EXPECT(is_shared(ctx, p.get_context())); EXPECT(is_shared(ctx, p.get_context()));
auto eval = p.eval(m); return migraphx::gpu::from_gpu(p.eval(m));
auto ret_val = migraphx::gpu::from_gpu(eval);
return ret_val;
} }
template <class V> template <class V>
......
#include <test.hpp>
#include <basic_ops.hpp>
#include <migraphx/program.hpp>
#include <migraphx/instruction.hpp>
#include <migraphx/generate.hpp>
#include <migraphx/gpu/target.hpp>
#include <migraphx/cpu/target.hpp>
#include <migraphx/gpu/hip.hpp>
#include <migraphx/verify_args.hpp>
migraphx::program create_program()
{
migraphx::program p;
auto in1 = p.add_parameter("0", migraphx::shape{migraphx::shape::float_type, {32, 64, 1, 1}});
auto in2 = p.add_parameter("1", migraphx::shape{migraphx::shape::float_type, {64, 64, 1, 1}});
auto p1 = p.add_instruction(migraphx::op::convolution{}, in1, in2);
auto in3 = p.add_parameter("2", migraphx::shape{migraphx::shape::float_type, {64, 64, 1, 1}});
auto p2 = p.add_instruction(migraphx::op::convolution{}, in1, in3);
p.add_instruction(migraphx::op::concat{1}, p1, p2);
return p;
}
migraphx::argument run_gpu()
{
setenv("MIGRAPHX_DISABLE_NULL_STREAM", "1", 1);
migraphx::program p = create_program();
p.compile(migraphx::gpu::target{});
migraphx::program::parameter_map m;
for(auto&& x : p.get_parameter_shapes())
{
m[x.first] = migraphx::gpu::to_gpu(migraphx::generate_argument(x.second));
}
auto ret_val = migraphx::gpu::from_gpu(p.eval(m));
p.finish();
return ret_val;
}
migraphx::argument run_cpu()
{
migraphx::program p = create_program();
p.compile(migraphx::cpu::target{});
migraphx::program::parameter_map m;
for(auto&& x : p.get_parameter_shapes())
{
m[x.first] = migraphx::generate_argument(x.second);
}
return p.eval(m);
}
void gpu_stream_execution_test()
{
auto result1 = run_gpu();
auto result2 = run_cpu();
verify_args("test", result2, result1);
}
int main() { gpu_stream_execution_test(); }
...@@ -36,6 +36,18 @@ inline std::ostream& operator<<(std::ostream& s, std::nullptr_t) ...@@ -36,6 +36,18 @@ inline std::ostream& operator<<(std::ostream& s, std::nullptr_t)
return s; return s;
} }
template <class T>
inline std::ostream& operator<<(std::ostream& s, const std::vector<T>& v)
{
s << "{ ";
for(auto&& x : v)
{
s << x << ", ";
}
s << "}";
return s;
}
template <class T, class U, class Operator> template <class T, class U, class Operator>
struct expression struct expression
{ {
......
...@@ -2,47 +2,15 @@ ...@@ -2,47 +2,15 @@
#include <migraphx/operators.hpp> #include <migraphx/operators.hpp>
#include <migraphx/generate.hpp> #include <migraphx/generate.hpp>
#include <migraphx/instruction.hpp> #include <migraphx/instruction.hpp>
#include <migraphx/dom_info.hpp>
#include <migraphx/common_header.hpp>
#include <migraphx/instruction.hpp>
#include <basic_ops.hpp> #include <basic_ops.hpp>
#include <test.hpp> #include <test.hpp>
struct set_stream
{
int stream = -1;
std::string name() const { return "gpu::set_stream"; }
migraphx::shape compute_shape(const std::vector<migraphx::shape>& inputs) const
{
if(inputs.empty())
return {};
else
return inputs.front();
}
};
struct find_concur
{
void get_concur(
migraphx::program* p,
int num_of_streams,
std::unordered_map<const migraphx::instruction*,
std::vector<std::vector<const migraphx::instruction*>>>& concur_instrs,
std::unordered_map<const migraphx::instruction*, int>& instr2_points) const
{
migraphx::dom_info info(p);
info.compute_dom(true);
info.propagate_splits(num_of_streams, concur_instrs, instr2_points);
}
};
struct memory_coloring_target struct memory_coloring_target
{ {
std::string name() const { return "memory_coloring"; } std::string name() const { return "memory_coloring"; }
std::vector<migraphx::pass> get_passes(migraphx::context&) const std::vector<migraphx::pass> get_passes(migraphx::context&) const
{ {
return {migraphx::memory_coloring{"allocate", 4, find_concur{}, true}}; return {migraphx::memory_coloring{"allocate", true}};
} }
migraphx::context get_context() const { return {}; } migraphx::context get_context() const { return {}; }
}; };
...@@ -639,40 +607,4 @@ TEST_CASE(literal_test) ...@@ -639,40 +607,4 @@ TEST_CASE(literal_test)
CHECK(lit == result); CHECK(lit == result);
} }
TEST_CASE(concurrent_test)
{
migraphx::program p;
auto in = p.add_parameter("0", migraphx::shape{migraphx::shape::float_type, {40}});
auto a1 = add_alloc(p, {migraphx::shape::float_type, {40}});
auto p1 = p.add_instruction(pass_op{}, a1, in);
p.insert_instruction(p1, set_stream{0});
p1->set_stream(0);
auto a2 = add_alloc(p, {migraphx::shape::float_type, {40}});
auto p2 = p.add_instruction(pass_op{}, a2, p1);
p2->set_stream(0);
auto a4 = add_alloc(p, {migraphx::shape::float_type, {40}});
auto p4 = p.add_instruction(pass_op{}, a4, p2);
p4->set_stream(0);
auto a3 = add_alloc(p, {migraphx::shape::float_type, {40}});
auto p3 = p.add_instruction(pass_op{}, a3, p1);
p3->set_stream(1);
p.insert_instruction(p3, set_stream{1});
auto a5 = add_alloc(p, {migraphx::shape::float_type, {40}});
auto p5 = p.add_instruction(pass_op{}, a5, p3);
p5->set_stream(1);
auto a6 = add_alloc(p, {migraphx::shape::float_type, {40}});
auto p6 = p.add_instruction(pass_op{}, a6, p1);
p6->set_stream(2);
p.insert_instruction(p6, set_stream{2});
auto a7 = add_alloc(p, {migraphx::shape::float_type, {40}});
auto p7 = p.add_instruction(pass_op{}, a7, p6);
p7->set_stream(2);
auto a8 = add_alloc(p, {migraphx::shape::float_type, {40}});
auto p8 = p.add_instruction(migraphx::op::concat{0}, a8, p4, p5, p7);
p8->set_stream(0);
p.insert_instruction(p8, set_stream{0});
p.compile(memory_coloring_target{});
CHECK(p.get_parameter_shape("scratch").bytes() == 960);
}
int main(int argc, const char* argv[]) { test::run(argc, argv); } int main(int argc, const char* argv[]) { test::run(argc, argv); }
This diff is collapsed.
#include <migraphx/pre_scheduling.hpp>
#include <migraphx/operators.hpp>
#include <migraphx/generate.hpp>
#include <migraphx/instruction.hpp>
#include <migraphx/program.hpp>
#include <basic_ops.hpp>
#include <test.hpp>
struct set_stream
{
int stream = -1;
std::string name() const { return "set_stream"; }
migraphx::shape compute_shape(const std::vector<migraphx::shape>& inputs) const
{
if(inputs.empty())
return {};
else
return inputs.front();
}
};
struct create_events
{
int num_of_events = 0;
std::string name() const { return "gpu::create_events"; }
migraphx::shape compute_shape(const std::vector<migraphx::shape>& inputs) const
{
if(inputs.empty())
return {};
else
return inputs.front();
}
};
struct weight_func
{
weight_func()
{
weight_map["@param"] = std::make_pair(1, 1);
weight_map["@literal"] = std::make_pair(1, 1);
};
std::pair<int, int> operator()(const migraphx::operation& op)
{
if(weight_map.find(op.name()) != weight_map.end())
return weight_map[op.name()];
else
return std::make_pair(1, 0);
}
std::unordered_map<std::string, std::pair<int, int>> weight_map;
};
struct insert_instruction
{
void insert_stream(migraphx::program* p, migraphx::instruction_ref ins, int stream)
{
p->insert_instruction(ins, set_stream{stream});
}
void insert_create_events(migraphx::program*, migraphx::instruction_ref, int) {}
void insert_record_event(migraphx::program*, migraphx::instruction_ref, int) {}
void insert_wait_event(migraphx::program*, migraphx::instruction_ref, int) {}
};
struct stream_execution_target
{
struct context
{
void finish() const {}
void set_stream(int) {}
void create_events(int) {}
void record_event(int) {}
void wait_event(int) {}
};
migraphx::context ctx = context{};
std::string name() const { return "stream_execution"; }
std::vector<migraphx::pass> get_passes(migraphx::context&) const
{
return {migraphx::pre_scheduling{weight_func(), 2, insert_instruction{}, true}};
}
migraphx::context get_context() const { return {ctx}; }
};
TEST_CASE(test1)
{
migraphx::program p;
auto in1 =
p.add_parameter("0", migraphx::shape{migraphx::shape::float_type, {32, 256, 35, 35}});
auto l1 =
p.add_literal(migraphx::generate_literal({migraphx::shape::float_type, {64, 256, 1, 1}}));
auto p1 = p.add_instruction(migraphx::op::convolution{}, in1, l1);
auto l2 =
p.add_literal(migraphx::generate_literal({migraphx::shape::float_type, {48, 256, 1, 1}}));
auto p2 = p.add_instruction(migraphx::op::convolution{}, in1, l2);
p.add_instruction(migraphx::op::concat{1}, p1, p2);
p.compile(stream_execution_target{});
std::cout << p << std::endl;
CHECK(std::count_if(
p.begin(), p.end(), [](auto&& ins) { return ins.name() == "set_stream"; }) == 3);
CHECK(std::count_if(p.begin(), p.end(), [](auto&& ins) { return ins.get_stream() == 0; }) == 2);
CHECK(std::count_if(p.begin(), p.end(), [](auto&& ins) { return ins.get_stream() == 1; }) == 1);
}
int main(int argc, const char* argv[]) { test::run(argc, argv); }
...@@ -27,11 +27,12 @@ struct context ...@@ -27,11 +27,12 @@ struct context
<% <%
interface('context', interface('context',
virtual('finish', returns='void', const=True), virtual('finish', returns='void', const=True)
) )
%> %>
#endif #endif
} // namespace MIGRAPHX_INLINE_NS } // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx } // namespace migraphx
......
#ifndef MIGRAPHX_GUARD_FIND_CONCUR_HPP
#define MIGRAPHX_GUARD_FIND_CONCUR_HPP
#include <cassert>
#include <string>
#include <functional>
#include <memory>
#include <type_traits>
#include <utility>
#include <unordered_map>
#include <vector>
#include <migraphx/instruction.hpp>
namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS {
struct program;
#ifdef DOXYGEN
/// An interface for target-dependent analysis to find concurrent instructions
/// executing in different streams.
struct find_concur
{
void get_concur(program* p,
int num_of_streams,
std::unordered_map<const instruction*,
std::vector<std::vector<const instruction*>>>& concur_instrs,
std::unordered_map<const instruction*, int>& instr2_points);
} const;
#else
<%
interface('find_concur',
virtual('get_concur', returns='void', p = 'program*', num_of_stream = 'int', concur_instrs = 'std::unordered_map<const instruction*, std::vector<std::vector<const instruction*>>>&', input = 'std::unordered_map<const instruction*, int>&', const=True)
)
%>
#endif
} // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx
#endif
#ifndef MIGRAPHX_GUARD_INSERT_INSTRUCTION_HPP
#define MIGRAPHX_GUARD_INSERT_INSTRUCTION_HPP
#include <cassert>
#include <string>
#include <functional>
#include <memory>
#include <type_traits>
#include <utility>
#include <migraphx/instruction_ref.hpp>
namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS {
struct program;
#ifdef DOXYGEN
/// An interface for target-dependent instruction insertion.
/// for multi-stream execution.
struct insert_instruction
{
void insert_create_events(program* p, instruction_ref ins, int num_of_events);
void insert_record_event(program* p, instruction_ref ins, int event);
void insert_wait_event(program* p, instruction_ref ins, int event);
void insert_stream(program* p, instruction_ref ins, int stream);
};
#else
<%
interface('insert_instruction',
virtual('insert_create_events', returns='void', p = 'program*', ins ='instruction_ref', input = 'int'),
virtual('insert_record_event', returns='void', p = 'program*', ins ='instruction_ref', input = 'int'),
virtual('insert_wait_event', returns='void', p = 'program*', ins = 'instruction_ref', input = 'int'),
virtual('insert_stream', returns='void', p = 'program*', ins ='instruction_ref', input = 'int')
)
%>
#endif
} // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx
#endif
#ifndef MIGRAPHX_GUARD_SCHEDULE_MODEL_HPP
#define MIGRAPHX_GUARD_SCHEDULE_MODEL_HPP
#include <cassert>
#include <string>
#include <functional>
#include <memory>
#include <type_traits>
#include <utility>
#include <migraphx/config.hpp>
#include <migraphx/instruction_ref.hpp>
#include <vector>
namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS {
struct program;
struct operation;
#ifdef DOXYGEN
/// An interface for target-dependent model for the scheduler
struct schedule_model
{
/// Get the number of concurrent instruction allowed
std::size_t concurrency() const;
/// Schedule a concurrent instruction
void sched(program& p, instruction_ref ins, std::size_t n) const;
// Insert necessary waits before an instruction
void wait(program& p, instruction_ref ins, std::size_t wait_id) const;
// Insert necessary records after an instruction
void record(program& p, instruction_ref ins, std::size_t wait_id) const;
/// Compute weights for an operation
std::size_t weight(const operation& op) const;
};
#else
<%
interface('schedule_model',
virtual('concurrency', returns='std::size_t', const=True),
virtual('sched', p='program&', ins='instruction_ref', n='std::size_t', const=True),
virtual('wait', p='program&', ins='instruction_ref', wait_id='std::size_t', const=True),
virtual('record', p='program&', ins='instruction_ref', wait_id='std::size_t', const=True),
virtual('weight', returns='std::size_t', op='const operation&', const=True)
)
%>
#endif
} // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx
#endif
import string, sys, re, os import string, sys, re, os
trivial = [
'std::size_t',
'instruction_ref'
]
headers = ''' headers = '''
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
...@@ -286,7 +292,7 @@ def convert_member(d, struct_name): ...@@ -286,7 +292,7 @@ def convert_member(d, struct_name):
member['this'] = x member['this'] = x
if 'const' in t: if 'const' in t:
member['member_const'] = 'const' member['member_const'] = 'const'
if t.endswith(('&', '*')): if t.endswith(('&', '*')) or t in trivial:
if use_member: member_args.append(x) if use_member: member_args.append(x)
args.append(arg_name) args.append(arg_name)
else: else:
......
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