Skip to content

Commit

Permalink
Build ONNX Server application on Windows (microsoft#57)
Browse files Browse the repository at this point in the history
* Gets Boost compiling on Windows

* Fix integer conversion and comparison problems

* Use size_t in converter_tests instead of int

* Fix hosting integration tests on Windows

* Removes checks for port because it's an unsigned short

* Fixes comparison between signed and unsigned data types

* Pip install protobuf and numpy
  • Loading branch information
tmccrmck authored Apr 27, 2019
1 parent 1cd43ab commit e7cfdc0
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 74 deletions.
33 changes: 28 additions & 5 deletions cmake/get_boost.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,18 @@ set(BOOST_USE_STATIC_LIBS true CACHE BOOL "")

set(BOOST_COMPONENTS program_options system thread)

# These components are only needed for Windows
if(WIN32)
message(FATAL_ERROR "Windows not currently supported")
list(APPEND BOOST_COMPONENTS date_time regex)
endif()

# MSVC doesn't set these variables
if(WIN32)
set(CMAKE_STATIC_LIBRARY_PREFIX lib)
set(CMAKE_SHARED_LIBRARY_PREFIX lib)
endif()

# Set lib prefixes and suffixes for linking
if(BOOST_USE_STATIC_LIBS)
set(LIBRARY_PREFIX ${CMAKE_STATIC_LIBRARY_PREFIX})
set(LIBRARY_SUFFIX ${CMAKE_STATIC_LIBRARY_SUFFIX})
Expand All @@ -19,6 +27,7 @@ else()
set(LIBRARY_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX})
endif()

# Create list of components in Boost format
foreach(component ${BOOST_COMPONENTS})
list(APPEND BOOST_COMPONENTS_FOR_BUILD --with-${component})
endforeach()
Expand All @@ -43,6 +52,16 @@ macro(DOWNLOAD_BOOST)
set(VARIANT "debug")
endif()

set(WINDOWS_B2_OPTIONS)
set(WINDOWS_LIB_NAME_SCHEME)
if(WIN32)
set(BOOTSTRAP_FILE_TYPE "bat")
set(WINDOWS_B2_OPTIONS "toolset=msvc-14.1" "architecture=x86" "address-model=64")
set(WINDOWS_LIB_NAME_SCHEME "-vc141-mt-gd-x64-1_69")
else()
set(BOOTSTRAP_FILE_TYPE "sh")
endif()

message(STATUS "Adding Boost components")
include(ExternalProject)
ExternalProject_Add(
Expand All @@ -52,21 +71,25 @@ macro(DOWNLOAD_BOOST)
DOWNLOAD_DIR ${BOOST_ROOT_DIR}
SOURCE_DIR ${BOOST_ROOT_DIR}
UPDATE_COMMAND ""
CONFIGURE_COMMAND ./bootstrap.sh --prefix=${BOOST_ROOT_DIR}
BUILD_COMMAND ./b2 install ${BOOST_MAYBE_STATIC} --prefix=${BOOST_ROOT_DIR} variant=${VARIANT} ${BOOST_COMPONENTS_FOR_BUILD}
CONFIGURE_COMMAND ./bootstrap.${BOOTSTRAP_FILE_TYPE} --prefix=${BOOST_ROOT_DIR}
BUILD_COMMAND ./b2 install ${BOOST_MAYBE_STATIC} --prefix=${BOOST_ROOT_DIR} variant=${VARIANT} ${WINDOWS_B2_OPTIONS} ${BOOST_COMPONENTS_FOR_BUILD}
BUILD_IN_SOURCE true
INSTALL_COMMAND ""
INSTALL_DIR ${BOOST_ROOT_DIR}
LOG_BUILD ON
)

# Set include folders
ExternalProject_Get_Property(Boost INSTALL_DIR)
set(Boost_INCLUDE_DIR ${INSTALL_DIR}/include)
if(WIN32)
set(Boost_INCLUDE_DIR ${INSTALL_DIR}/include/boost-1_69)
endif()

# Set libraries to link
macro(libraries_to_fullpath varname)
set(${varname})
foreach(component ${BOOST_COMPONENTS})
list(APPEND ${varname} ${INSTALL_DIR}/lib/${LIBRARY_PREFIX}boost_${component}${LIBRARY_SUFFIX})
list(APPEND ${varname} ${INSTALL_DIR}/lib/${LIBRARY_PREFIX}boost_${component}${WINDOWS_LIB_NAME_SCHEME}${LIBRARY_SUFFIX})
endforeach()
endmacro()

Expand Down
6 changes: 4 additions & 2 deletions cmake/onnxruntime_server.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
set(SERVER_APP_NAME "onnxruntime_server")

# Generate .h and .cc files from protobuf file
add_library(server_proto
${ONNXRUNTIME_ROOT}/server/protobuf/predict.proto)
add_library(server_proto ${ONNXRUNTIME_ROOT}/server/protobuf/predict.proto)
if(WIN32)
target_compile_options(server_proto PRIVATE "/wd4125" "/wd4456")
endif()
target_include_directories(server_proto PUBLIC $<TARGET_PROPERTY:protobuf::libprotobuf,INTERFACE_INCLUDE_DIRECTORIES> "${CMAKE_CURRENT_BINARY_DIR}/.." ${CMAKE_CURRENT_BINARY_DIR}/onnx)
target_compile_definitions(server_proto PUBLIC $<TARGET_PROPERTY:protobuf::libprotobuf,INTERFACE_COMPILE_DEFINITIONS>)
onnxruntime_protobuf_generate(APPEND_PATH IMPORT_DIRS ${REPO_ROOT}/cmake/external/protobuf/src ${ONNXRUNTIME_ROOT}/server/protobuf ${ONNXRUNTIME_ROOT}/core/protobuf TARGET server_proto)
Expand Down
28 changes: 14 additions & 14 deletions onnxruntime/server/converter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ common::Status MLValueToTensorProto(const onnxruntime::MLValue& ml_value, bool u
if (using_raw_data) {
tensor_proto.set_raw_data(data, tensor.Size());
} else {
for (int i = 0, count = tensor.Shape().Size(); i < count; ++i) {
for (size_t i = 0, count = tensor.Shape().Size(); i < count; ++i) {
tensor_proto.add_float_data(data[i]);
}
}
Expand All @@ -96,7 +96,7 @@ common::Status MLValueToTensorProto(const onnxruntime::MLValue& ml_value, bool u
if (using_raw_data) {
tensor_proto.set_raw_data(data, tensor.Size());
} else {
for (int i = 0, count = tensor.Shape().Size(); i < count; ++i) {
for (size_t i = 0, count = tensor.Shape().Size(); i < count; ++i) {
tensor_proto.add_int32_data(data[i]);
}
}
Expand All @@ -108,7 +108,7 @@ common::Status MLValueToTensorProto(const onnxruntime::MLValue& ml_value, bool u
tensor_proto.set_raw_data(data, tensor.Size());
} else {
auto i32data = reinterpret_cast<const int32_t*>(data);
for (int i = 0, count = 1 + ((tensor.Size() - 1) / sizeof(int32_t)); i < count; ++i) {
for (size_t i = 0, count = 1 + ((tensor.Size() - 1) / sizeof(int32_t)); i < count; ++i) {
tensor_proto.add_int32_data(i32data[i]);
}
}
Expand All @@ -120,7 +120,7 @@ common::Status MLValueToTensorProto(const onnxruntime::MLValue& ml_value, bool u
tensor_proto.set_raw_data(data, tensor.Size());
} else {
auto i32data = reinterpret_cast<const int32_t*>(data);
for (int i = 0, count = 1 + ((tensor.Size() - 1) / sizeof(int32_t)); i < count; ++i) {
for (size_t i = 0, count = 1 + ((tensor.Size() - 1) / sizeof(int32_t)); i < count; ++i) {
tensor_proto.add_int32_data(i32data[i]);
}
}
Expand All @@ -132,7 +132,7 @@ common::Status MLValueToTensorProto(const onnxruntime::MLValue& ml_value, bool u
tensor_proto.set_raw_data(data, tensor.Size());
} else {
auto i32data = reinterpret_cast<const int32_t*>(data);
for (int i = 0, count = 1 + ((tensor.Size() - 1) / sizeof(int32_t)); i < count; ++i) {
for (size_t i = 0, count = 1 + ((tensor.Size() - 1) / sizeof(int32_t)); i < count; ++i) {
tensor_proto.add_int32_data(i32data[i]);
}
}
Expand All @@ -144,7 +144,7 @@ common::Status MLValueToTensorProto(const onnxruntime::MLValue& ml_value, bool u
tensor_proto.set_raw_data(data, tensor.Size());
} else {
auto i32data = reinterpret_cast<const int32_t*>(data);
for (int i = 0, count = 1 + ((tensor.Size() - 1) / sizeof(int32_t)); i < count; ++i) {
for (size_t i = 0, count = 1 + ((tensor.Size() - 1) / sizeof(int32_t)); i < count; ++i) {
tensor_proto.add_int32_data(i32data[i]);
}
}
Expand All @@ -156,7 +156,7 @@ common::Status MLValueToTensorProto(const onnxruntime::MLValue& ml_value, bool u
tensor_proto.set_raw_data(data, tensor.Size());
} else {
auto i32data = reinterpret_cast<const int32_t*>(data);
for (int i = 0, count = 1 + ((tensor.Size() - 1) / sizeof(int32_t)); i < count; ++i) {
for (size_t i = 0, count = 1 + ((tensor.Size() - 1) / sizeof(int32_t)); i < count; ++i) {
tensor_proto.add_int32_data(i32data[i]);
}
}
Expand All @@ -168,7 +168,7 @@ common::Status MLValueToTensorProto(const onnxruntime::MLValue& ml_value, bool u
tensor_proto.set_raw_data(data, tensor.Size());
} else {
auto i32data = reinterpret_cast<const int32_t*>(data);
for (int i = 0, count = 1 + ((tensor.Size() - 1) / sizeof(int32_t)); i < count; ++i) {
for (size_t i = 0, count = 1 + ((tensor.Size() - 1) / sizeof(int32_t)); i < count; ++i) {
tensor_proto.add_int32_data(i32data[i]);
}
}
Expand All @@ -188,7 +188,7 @@ common::Status MLValueToTensorProto(const onnxruntime::MLValue& ml_value, bool u
tensor_proto.set_raw_data(raw_data.data(), raw_data.size() * sizeof(uint16_t));
} else {
auto i32data = reinterpret_cast<const int32_t*>(raw_data.data());
for (int i = 0, count = 1 + ((tensor.Size() - 1) / sizeof(int32_t)); i < count; ++i) {
for (size_t i = 0, count = 1 + ((tensor.Size() - 1) / sizeof(int32_t)); i < count; ++i) {
tensor_proto.add_int32_data(i32data[i]);
}
}
Expand All @@ -197,7 +197,7 @@ common::Status MLValueToTensorProto(const onnxruntime::MLValue& ml_value, bool u
case onnx::TensorProto_DataType_STRING: { // Target: string_data
// string could not be written into "raw_data"
const auto* data = tensor.Data<std::string>();
for (int i = 0, count = tensor.Shape().Size(); i < count; ++i) {
for (size_t i = 0, count = tensor.Shape().Size(); i < count; ++i) {
tensor_proto.add_string_data(data[i]);
}
break;
Expand All @@ -207,7 +207,7 @@ common::Status MLValueToTensorProto(const onnxruntime::MLValue& ml_value, bool u
if (using_raw_data) {
tensor_proto.set_raw_data(data, tensor.Size());
} else {
for (int x = 0, loop_length = tensor.Shape().Size(); x < loop_length; ++x) {
for (size_t x = 0, loop_length = tensor.Shape().Size(); x < loop_length; ++x) {
tensor_proto.add_int64_data(data[x]);
}
}
Expand All @@ -219,7 +219,7 @@ common::Status MLValueToTensorProto(const onnxruntime::MLValue& ml_value, bool u
tensor_proto.set_raw_data(data, tensor.Size());
} else {
auto u64data = reinterpret_cast<const uint64_t*>(data);
for (int i = 0, count = 1 + ((tensor.Size() - 1) / sizeof(uint64_t)); i < count; ++i) {
for (size_t i = 0, count = 1 + ((tensor.Size() - 1) / sizeof(uint64_t)); i < count; ++i) {
tensor_proto.add_uint64_data(u64data[i]);
}
}
Expand All @@ -230,7 +230,7 @@ common::Status MLValueToTensorProto(const onnxruntime::MLValue& ml_value, bool u
if (using_raw_data) {
tensor_proto.set_raw_data(data, tensor.Size());
} else {
for (int x = 0, loop_length = tensor.Shape().Size(); x < loop_length; ++x) {
for (size_t x = 0, loop_length = tensor.Shape().Size(); x < loop_length; ++x) {
tensor_proto.add_uint64_data(data[x]);
}
}
Expand All @@ -241,7 +241,7 @@ common::Status MLValueToTensorProto(const onnxruntime::MLValue& ml_value, bool u
if (using_raw_data) {
tensor_proto.set_raw_data(data, tensor.Size());
} else {
for (int x = 0, loop_length = tensor.Shape().Size(); x < loop_length; ++x) {
for (size_t x = 0, loop_length = tensor.Shape().Size(); x < loop_length; ++x) {
tensor_proto.add_double_data(data[x]);
}
}
Expand Down
2 changes: 1 addition & 1 deletion onnxruntime/server/http/predict_request_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ static bool ParseRequestPayload(const HttpContext& context, SupportedContentType
break;
}
case SupportedContentType::PbByteArray: {
bool parse_succeeded = predictRequest.ParseFromArray(body.data(), body.size());
bool parse_succeeded = predictRequest.ParseFromArray(body.data(), static_cast<int>(body.size()));
if (!parse_succeeded) {
error_code = http::status::bad_request;
error_message = "Invalid payload.";
Expand Down
5 changes: 1 addition & 4 deletions onnxruntime/server/server_configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class ServerConfiguration {
const std::string full_desc = "ONNX Server: host an ONNX model with ONNX Runtime";
std::string model_path;
std::string address = "0.0.0.0";
int http_port = 8001;
unsigned short http_port = 8001;
int num_http_threads = std::thread::hardware_concurrency();
onnxruntime::logging::Severity logging_level{};

Expand Down Expand Up @@ -97,9 +97,6 @@ class ServerConfiguration {
} else if (num_http_threads <= 0) {
PrintHelp(std::cerr, "num_http_threads must be greater than 0");
return Result::ExitFailure;
} else if (http_port < 0 || http_port > 65535) {
PrintHelp(std::cerr, "http_port input invalid");
return Result::ExitFailure;
} else if (!file_exists(model_path)) {
PrintHelp(std::cerr, "model_path must be the location of a valid file");
return Result::ExitFailure;
Expand Down
19 changes: 14 additions & 5 deletions onnxruntime/test/server/integration_tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import datetime
import socket
import errno
import sys

import predict_pb2
import onnx_ml_pb2
Expand All @@ -22,12 +23,20 @@ def test_log(str):


def is_process_killed(pid):
try:
os.kill(pid, 0)
except OSError:
return False
if sys.platform.startswith("win"):
process_name = 'onnxruntime_host.exe'
call = 'TASKLIST', '/FI', 'imagename eq {0}'.format(process_name)
output = subprocess.check_output(call).decode('utf-8')
print(output)
last_line = output.strip().split('\r\n')[-1]
return not last_line.lower().startswith(process_name)
else:
return True
try:
os.kill(pid, 0)
except OSError:
return False
else:
return True


def decode_base64_string(s, count_and_type):
Expand Down
Loading

0 comments on commit e7cfdc0

Please sign in to comment.