"docs_zh_CN/vscode:/vscode.git/clone" did not exist on "f3dfc4135b2081d18544d6a6493ea08e6e01583c"
Unverified Commit 37fbabf5 authored by Paul Fultz II's avatar Paul Fultz II Committed by GitHub
Browse files

Add msgpack serialization (#596)



* Add msgpack serialization

* Formatting

* Fix compiler errors on gcc

* Remove redundant initialization

* Use type to fix compile error with gcc 5

* Formatting

* Add more tests

* Change to migraphx throw

* Fix message
Co-authored-by: default avatarShucai Xiao <shucai.xiao@amd.com>
Co-authored-by: default avatarmvermeulen <5479696+mvermeulen@users.noreply.github.com>
parent 63563da2
...@@ -6,3 +6,4 @@ nlohmann/json@v3.8.0 ...@@ -6,3 +6,4 @@ nlohmann/json@v3.8.0
blaze,https://bitbucket.org/blaze-lib/blaze/get/f0755dea0e03.tar.gz -X header -DHEADER_DIR=blaze blaze,https://bitbucket.org/blaze-lib/blaze/get/f0755dea0e03.tar.gz -X header -DHEADER_DIR=blaze
half,https://github.com/pfultz2/half/archive/1.12.0.tar.gz -X header -H sha256:0a08660b68abb176ebc2a0cdf8de46e3182a7f46c66443bb80dbfaaec98cf969 half,https://github.com/pfultz2/half/archive/1.12.0.tar.gz -X header -H sha256:0a08660b68abb176ebc2a0cdf8de46e3182a7f46c66443bb80dbfaaec98cf969
pybind/pybind11@v2.2.4 -DPYBIND11_TEST=Off --build pybind/pybind11@v2.2.4 -DPYBIND11_TEST=Off --build
msgpack/msgpack-c@cpp-3.3.0 -DMSGPACK_BUILD_TESTS=Off
\ No newline at end of file
...@@ -19,6 +19,7 @@ add_library(migraphx ...@@ -19,6 +19,7 @@ add_library(migraphx
env.cpp env.cpp
generate.cpp generate.cpp
instruction.cpp instruction.cpp
msgpack.cpp
program.cpp program.cpp
quantization.cpp quantization.cpp
reduce_dims.cpp reduce_dims.cpp
...@@ -46,6 +47,11 @@ find_path(HALF_INCLUDE_DIR half.hpp) ...@@ -46,6 +47,11 @@ find_path(HALF_INCLUDE_DIR half.hpp)
# TODO: Fix the incorrect path # TODO: Fix the incorrect path
target_include_directories(migraphx SYSTEM PUBLIC $<BUILD_INTERFACE:${HALF_INCLUDE_DIR}>) target_include_directories(migraphx SYSTEM PUBLIC $<BUILD_INTERFACE:${HALF_INCLUDE_DIR}>)
find_package(msgpack REQUIRED)
target_link_libraries(migraphx PRIVATE msgpackc-cxx)
# Make this available to the tests
target_link_libraries(migraphx INTERFACE $<BUILD_INTERFACE:msgpackc-cxx>)
set(PACKAGE_DEPENDS) set(PACKAGE_DEPENDS)
add_subdirectory(api) add_subdirectory(api)
......
#ifndef MIGRAPHX_GUARD_RTGLIB_MSGPACK_HPP
#define MIGRAPHX_GUARD_RTGLIB_MSGPACK_HPP
#include <migraphx/config.hpp>
#include <migraphx/value.hpp>
namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS {
std::vector<char> to_msgpack(const value& v);
value from_msgpack(const std::vector<char>& buffer);
} // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx
#endif
...@@ -291,7 +291,7 @@ struct value ...@@ -291,7 +291,7 @@ struct value
friend std::ostream& operator<<(std::ostream& os, const value& d); friend std::ostream& operator<<(std::ostream& os, const value& d);
void debug_print() const; void debug_print(bool show_type = false) const;
private: private:
type_t get_type() const; type_t get_type() const;
......
#include <migraphx/msgpack.hpp>
#include <migraphx/serialize.hpp>
#include <msgpack.hpp>
namespace msgpack {
MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)
{
namespace adaptor {
template <>
struct convert<migraphx::value>
{
const msgpack::object& operator()(const msgpack::object& o, migraphx::value& v) const
{
switch(o.type)
{
case msgpack::type::NIL:
{
v = nullptr;
break;
}
case msgpack::type::BOOLEAN:
{
v = o.as<bool>();
break;
}
case msgpack::type::POSITIVE_INTEGER:
{
v = o.as<std::uint64_t>();
break;
}
case msgpack::type::NEGATIVE_INTEGER:
{
v = o.as<std::int64_t>();
break;
}
case msgpack::type::FLOAT32:
case msgpack::type::FLOAT64:
{
v = o.as<double>();
break;
}
case msgpack::type::STR:
{
v = o.as<std::string>();
break;
}
case msgpack::type::BIN: { MIGRAPHX_THROW("msgpack BIN type not supported.");
}
case msgpack::type::ARRAY:
{
migraphx::value r = migraphx::value::array{};
std::for_each(
o.via.array.ptr,
o.via.array.ptr + o.via.array.size,
[&](const msgpack::object& so) { r.push_back(so.as<migraphx::value>()); });
v = r;
break;
}
case msgpack::type::MAP:
{
migraphx::value r = migraphx::value::object{};
std::for_each(o.via.map.ptr,
o.via.map.ptr + o.via.map.size,
[&](const msgpack::object_kv& p) {
r[p.key.as<std::string>()] = p.val.as<migraphx::value>();
});
v = r;
break;
}
case msgpack::type::EXT: { MIGRAPHX_THROW("msgpack EXT type not supported.");
}
}
return o;
}
};
template <>
struct pack<migraphx::value>
{
template <class Stream>
void write(msgpack::packer<Stream>& o, const std::nullptr_t&) const
{
o.pack_nil();
}
template <class Stream, class T>
void write(msgpack::packer<Stream>& o, const T& x) const
{
o.pack(x);
}
template <class Stream>
void write(msgpack::packer<Stream>& o, const std::vector<migraphx::value>& v) const
{
if(v.empty())
{
o.pack_array(0);
return;
}
if(not v.front().get_key().empty())
{
o.pack_map(v.size());
for(auto&& x : v)
{
o.pack(x.get_key());
o.pack(x.without_key());
}
}
else
{
o.pack_array(v.size());
for(auto&& x : v)
{
o.pack(x);
}
}
}
template <class Stream>
packer<Stream>& operator()(msgpack::packer<Stream>& o, const migraphx::value& v) const
{
v.visit([&](auto&& x) { this->write(o, x); });
return o;
}
};
} // namespace adaptor
} // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)
} // namespace msgpack
namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS {
struct vector_stream
{
std::vector<char> buffer{};
vector_stream& write(const char* b, std::size_t n)
{
buffer.insert(buffer.end(), b, b + n);
return *this;
}
};
std::vector<char> to_msgpack(const value& v)
{
vector_stream vs;
msgpack::pack(vs, v);
return vs.buffer;
}
value from_msgpack(const std::vector<char>& buffer)
{
msgpack::object_handle oh = msgpack::unpack(buffer.data(), buffer.size());
return oh.get().as<value>();
}
} // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx
...@@ -435,7 +435,22 @@ std::ostream& operator<<(std::ostream& os, const value& d) ...@@ -435,7 +435,22 @@ std::ostream& operator<<(std::ostream& os, const value& d)
return os; return os;
} }
void value::debug_print() const { std::cout << *this << std::endl; } void value::debug_print(bool show_type) const
{
if(show_type)
{
switch(get_type())
{
#define MIGRAPHX_VALUE_GENERATE_TYPE_STRING_CASE(vt, cpp_type) \
case vt##_type: std::cout << #vt << ": "; break;
MIGRAPHX_VISIT_VALUE_TYPES(MIGRAPHX_VALUE_GENERATE_TYPE_STRING_CASE)
MIGRAPHX_VALUE_GENERATE_TYPE_STRING_CASE(null, )
MIGRAPHX_VALUE_GENERATE_TYPE_STRING_CASE(array, )
MIGRAPHX_VALUE_GENERATE_TYPE_STRING_CASE(object, )
}
}
std::cout << *this << std::endl;
}
} // namespace MIGRAPHX_INLINE_NS } // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx } // namespace migraphx
#include <migraphx/msgpack.hpp>
#include <migraphx/value.hpp>
#include <msgpack.hpp>
#include <map>
#include "test.hpp"
template <class T>
std::vector<char> msgpack_buffer(const T& src)
{
std::stringstream buffer;
msgpack::pack(buffer, src);
buffer.seekg(0);
std::string str = buffer.str();
return std::vector<char>(str.data(), str.data() + str.size());
}
TEST_CASE(test_msgpack_empty_value)
{
migraphx::value v;
auto buffer = migraphx::to_msgpack(v);
auto mp = migraphx::from_msgpack(buffer);
EXPECT(mp == v);
EXPECT(v.is_null());
EXPECT(mp.is_null());
}
TEST_CASE(test_msgpack_int)
{
migraphx::value v = 3;
auto buffer = migraphx::to_msgpack(v);
EXPECT(buffer == msgpack_buffer(3));
EXPECT(migraphx::from_msgpack(buffer).to<int>() == v.to<int>());
}
TEST_CASE(test_msgpack_int_negative)
{
migraphx::value v = -3;
auto buffer = migraphx::to_msgpack(v);
EXPECT(buffer == msgpack_buffer(-3));
EXPECT(migraphx::from_msgpack(buffer).to<int>() == v.to<int>());
}
TEST_CASE(test_msgpack_bool)
{
migraphx::value v = true;
auto buffer = migraphx::to_msgpack(v);
EXPECT(buffer == msgpack_buffer(true));
EXPECT(migraphx::from_msgpack(buffer) == v);
}
TEST_CASE(test_msgpack_float)
{
migraphx::value v = 3.0;
auto buffer = migraphx::to_msgpack(v);
EXPECT(buffer == msgpack_buffer(3.0));
EXPECT(migraphx::from_msgpack(buffer) == v);
}
TEST_CASE(test_msgpack_string)
{
migraphx::value v = "abc";
auto buffer = migraphx::to_msgpack(v);
EXPECT(buffer == msgpack_buffer("abc"));
EXPECT(migraphx::from_msgpack(buffer) == v);
}
TEST_CASE(test_msgpack_array)
{
migraphx::value v = {1, 2, 3};
auto buffer = migraphx::to_msgpack(v);
EXPECT(buffer == msgpack_buffer(std::vector<int>{1, 2, 3}));
EXPECT(migraphx::from_msgpack(buffer).to_vector<int>() == v.to_vector<int>());
}
TEST_CASE(test_msgpack_empty_array)
{
migraphx::value v = migraphx::value::array{};
auto buffer = migraphx::to_msgpack(v);
EXPECT(buffer == msgpack_buffer(std::vector<int>{}));
EXPECT(migraphx::from_msgpack(buffer) == v);
}
TEST_CASE(test_msgpack_object)
{
migraphx::value v = {{"one", 1.0}, {"three", 3.0}, {"two", 2.0}};
auto buffer = migraphx::to_msgpack(v);
EXPECT(buffer == msgpack_buffer(std::map<std::string, double>{
{"one", 1.0}, {"three", 3.0}, {"two", 2.0}}));
EXPECT(migraphx::from_msgpack(buffer) == v);
}
TEST_CASE(test_msgpack_empty_object)
{
migraphx::value v = migraphx::value::object{};
auto buffer = migraphx::to_msgpack(v);
EXPECT(buffer == msgpack_buffer(std::vector<int>{}));
auto u = migraphx::from_msgpack(buffer);
// This is not equal since an empty object becomes an empty array
EXPECT(u != v);
EXPECT(u.is_array());
EXPECT(u.size() == 0);
}
struct foo
{
double a;
std::string b;
MSGPACK_DEFINE_MAP(a, b);
};
TEST_CASE(test_msgpack_object_class)
{
migraphx::value v = {{"a", 1.0}, {"b", "abc"}};
auto buffer = migraphx::to_msgpack(v);
EXPECT(buffer == msgpack_buffer(foo{1.0, "abc"}));
EXPECT(migraphx::from_msgpack(buffer) == v);
}
TEST_CASE(test_msgpack_array_class)
{
migraphx::value v = {{{"a", 1.0}, {"b", "abc"}}, {{"a", 3.0}, {"b", "xyz"}}};
auto buffer = migraphx::to_msgpack(v);
EXPECT(buffer == msgpack_buffer(std::vector<foo>{foo{1.0, "abc"}, foo{3.0, "xyz"}}));
EXPECT(migraphx::from_msgpack(buffer) == v);
}
int main(int argc, const char* argv[]) { test::run(argc, argv); }
...@@ -9,6 +9,21 @@ TEST_CASE(value_default_construct) ...@@ -9,6 +9,21 @@ TEST_CASE(value_default_construct)
EXPECT(v.get_key().empty()); EXPECT(v.get_key().empty());
} }
TEST_CASE(value_construct_null)
{
migraphx::value v = nullptr;
EXPECT(v.is_null());
EXPECT(v.get_key().empty());
}
TEST_CASE(value_assign_null)
{
migraphx::value v;
v = nullptr;
EXPECT(v.is_null());
EXPECT(v.get_key().empty());
}
TEST_CASE(value_construct_int1) TEST_CASE(value_construct_int1)
{ {
EXPECT(migraphx::value(1).is_int64()); EXPECT(migraphx::value(1).is_int64());
......
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