diff --git a/.gitignore b/.gitignore index 76e76e8600..87424510f2 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ onnxruntime_profile*.json /csharp/**/bin/ docs/python/*.onnx *.onnx +onnxprofile_profile_test_*.json diff --git a/cmake/onnxruntime_framework.cmake b/cmake/onnxruntime_framework.cmake index d1924454f9..7e5bdfd8f8 100644 --- a/cmake/onnxruntime_framework.cmake +++ b/cmake/onnxruntime_framework.cmake @@ -11,8 +11,7 @@ source_group(TREE ${REPO_ROOT} FILES ${onnxruntime_framework_srcs}) add_library(onnxruntime_framework ${onnxruntime_framework_srcs}) -#TODO: remove ${eigen_INCLUDE_DIRS} from here -target_include_directories(onnxruntime_framework PRIVATE ${ONNXRUNTIME_ROOT} ${eigen_INCLUDE_DIRS} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) +target_include_directories(onnxruntime_framework PRIVATE ${ONNXRUNTIME_ROOT} PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${eigen_INCLUDE_DIRS}) onnxruntime_add_include_to_target(onnxruntime_framework onnxruntime_common gsl onnx onnx_proto protobuf::libprotobuf) set_target_properties(onnxruntime_framework PROPERTIES FOLDER "ONNXRuntime") # need onnx to build to create headers that this project includes @@ -23,3 +22,7 @@ if (WIN32) # Add Code Analysis properties to enable C++ Core checks. Have to do it via a props file include. set_target_properties(onnxruntime_framework PROPERTIES VS_USER_PROPS ${PROJECT_SOURCE_DIR}/ConfigureVisualStudioCodeAnalysis.props) endif() + +if(onnxruntime_USE_EIGEN_THREADPOOL) + target_compile_definitions(onnxruntime_framework PUBLIC USE_EIGEN_THREADPOOL) +endif() diff --git a/cmake/onnxruntime_providers.cmake b/cmake/onnxruntime_providers.cmake index 09e355b363..cd65727cf8 100644 --- a/cmake/onnxruntime_providers.cmake +++ b/cmake/onnxruntime_providers.cmake @@ -98,3 +98,7 @@ endif() if (onnxruntime_ENABLE_MICROSOFT_INTERNAL) include(onnxruntime_providers_internal.cmake) endif() + +if(onnxruntime_USE_EIGEN_THREADPOOL) + target_compile_definitions(onnxruntime_providers PUBLIC USE_EIGEN_THREADPOOL) +endif() diff --git a/cmake/onnxruntime_session.cmake b/cmake/onnxruntime_session.cmake index 3efeea02c0..1d55b7d5e1 100644 --- a/cmake/onnxruntime_session.cmake +++ b/cmake/onnxruntime_session.cmake @@ -12,8 +12,10 @@ source_group(TREE ${REPO_ROOT} FILES ${onnxruntime_session_srcs}) add_library(onnxruntime_session ${onnxruntime_session_srcs}) install(DIRECTORY ${PROJECT_SOURCE_DIR}/../include/onnxruntime/core/session DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/onnxruntime/core) onnxruntime_add_include_to_target(onnxruntime_session onnxruntime_common onnxruntime_framework gsl onnx onnx_proto protobuf::libprotobuf) -target_include_directories(onnxruntime_session PRIVATE ${ONNXRUNTIME_ROOT}) +target_include_directories(onnxruntime_session PRIVATE ${ONNXRUNTIME_ROOT} ${eigen_INCLUDE_DIRS}) add_dependencies(onnxruntime_session ${onnxruntime_EXTERNAL_DEPENDENCIES}) set_target_properties(onnxruntime_session PROPERTIES FOLDER "ONNXRuntime") - +if(onnxruntime_USE_EIGEN_THREADPOOL) + target_compile_definitions(onnxruntime_session PUBLIC USE_EIGEN_THREADPOOL) +endif() diff --git a/cmake/onnxruntime_unittests.cmake b/cmake/onnxruntime_unittests.cmake index 1eea0bd2da..5062a9db71 100644 --- a/cmake/onnxruntime_unittests.cmake +++ b/cmake/onnxruntime_unittests.cmake @@ -351,7 +351,8 @@ set(onnx_test_runner_common_srcs ${onnx_test_runner_src_dir}/TestCase.cc ${onnx_test_runner_src_dir}/TestCase.h ${onnx_test_runner_src_dir}/path_lib.h - ${onnx_test_runner_src_dir}/sync_api.h) + ${onnx_test_runner_src_dir}/sync_api.h + ${onnx_test_runner_src_dir}/sync_api.cc) if(WIN32) set(wide_get_opt_src_dir ${TEST_SRC_DIR}/win_getopt/wide) @@ -363,11 +364,12 @@ if(WIN32) target_include_directories(win_getopt_mb INTERFACE ${mb_get_opt_src_dir}/include) set_target_properties(win_getopt_mb PROPERTIES FOLDER "ONNXRuntimeTest") - set(onnx_test_runner_common_srcs ${onnx_test_runner_common_srcs} ${onnx_test_runner_src_dir}/sync_api_win.cc) + set(onnx_test_runner_common_srcs ${onnx_test_runner_common_srcs}) + set(GETOPT_LIB_WIDE win_getopt_wide) set(GETOPT_LIB win_getopt_mb) else() - set(onnx_test_runner_common_srcs ${onnx_test_runner_common_srcs} ${onnx_test_runner_src_dir}/onnxruntime_event.h ${onnx_test_runner_src_dir}/simple_thread_pool.h ${onnx_test_runner_src_dir}/sync_api_linux.cc) + set(onnx_test_runner_common_srcs ${onnx_test_runner_common_srcs} ${onnx_test_runner_src_dir}/onnxruntime_event.h ${onnx_test_runner_src_dir}/simple_thread_pool.h) if(HAS_FILESYSTEM_H OR HAS_EXPERIMENTAL_FILESYSTEM_H) set(FS_STDLIB stdc++fs) endif() diff --git a/onnxruntime/contrib_ops/cpu/attnlstm/deep_cpu_attn_lstm.cc b/onnxruntime/contrib_ops/cpu/attnlstm/deep_cpu_attn_lstm.cc index 4de2be7db8..23eb0cc8e1 100644 --- a/onnxruntime/contrib_ops/cpu/attnlstm/deep_cpu_attn_lstm.cc +++ b/onnxruntime/contrib_ops/cpu/attnlstm/deep_cpu_attn_lstm.cc @@ -8,7 +8,6 @@ #include "core/common/common.h" #include "core/common/logging/logging.h" -#include "core/common/task_thread_pool.h" #include "core/framework/allocator.h" namespace onnxruntime { @@ -340,16 +339,16 @@ static Status ValidateRnnInputsWithExtraInputFromState( W_shape[1] != hidden_size * WRB_dim_1_multipler || W_shape[2] != input_size) return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Input W must have shape {", - num_directions, ",", WRB_dim_1_multipler, "*", hidden_size, ",", - input_size, "}. Actual:", W_shape); + num_directions, ",", WRB_dim_1_multipler, "*", hidden_size, ",", + input_size, "}. Actual:", W_shape); if (R_shape.NumDimensions() != 3 || R_shape[0] != num_directions || R_shape[1] != hidden_size * WRB_dim_1_multipler || R_shape[2] != hidden_size) return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Input R must have shape {", - num_directions, ",", WRB_dim_1_multipler, "*", hidden_size, ",", - hidden_size, "}. Actual:", R_shape); + num_directions, ",", WRB_dim_1_multipler, "*", hidden_size, ",", + hidden_size, "}. Actual:", R_shape); if (B != nullptr) { auto& B_shape = B->Shape(); @@ -357,7 +356,7 @@ static Status ValidateRnnInputsWithExtraInputFromState( B_shape[0] != num_directions || B_shape[1] != 2 * WRB_dim_1_multipler * hidden_size) return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Input B must have shape {", - num_directions, ",", 2 * WRB_dim_1_multipler, "*", hidden_size, "}. Actual:", B_shape); + num_directions, ",", 2 * WRB_dim_1_multipler, "*", hidden_size, "}. Actual:", B_shape); } if (sequence_lens != nullptr) { @@ -365,7 +364,7 @@ static Status ValidateRnnInputsWithExtraInputFromState( if (sequence_lens_shape.NumDimensions() != 1 || sequence_lens_shape[0] != batch_size) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Input sequence_lens must have shape {", - batch_size, "}. Actual:", sequence_lens_shape); + batch_size, "}. Actual:", sequence_lens_shape); } auto sequence_len_entries = sequence_lens->DataAsSpan(); @@ -387,7 +386,7 @@ static Status ValidateRnnInputsWithExtraInputFromState( initial_h_shape[2] != hidden_size) return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Input initial_h must have shape {", - num_directions, ",", batch_size, ",", hidden_size, "}. Actual:", initial_h_shape); + num_directions, ",", batch_size, ",", hidden_size, "}. Actual:", initial_h_shape); } return Status::OK(); @@ -403,8 +402,8 @@ Status DeepCpuAttnLstmOp::ValidateInputs( auto memory_shape = attn_memory.Shape(); if (memory_shape.NumDimensions() != 3 || memory_shape[0] != batch_size) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Attention mechanism memory shape error! Expected: {", batch_size, - "}, actural: ", memory_shape); + "Attention mechanism memory shape error! Expected: {", batch_size, + "}, actural: ", memory_shape); } const int max_memory_step = gsl::narrow(memory_shape[1]); const int memory_depth = gsl::narrow(memory_shape[2]); @@ -412,8 +411,8 @@ Status DeepCpuAttnLstmOp::ValidateInputs( auto memory_seq_lens_shape = attn_memory_seq_lens->Shape(); if (memory_seq_lens_shape.NumDimensions() != 1 || memory_seq_lens_shape[0] != batch_size) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Attention mechanism memory sequence lengths must have shape {", batch_size, - "}, actural: ", memory_seq_lens_shape); + "Attention mechanism memory sequence lengths must have shape {", batch_size, + "}, actural: ", memory_seq_lens_shape); } const gsl::span mem_seq_lens_span = attn_memory_seq_lens->DataAsSpan(); auto item_not_in_range = std::find_if( @@ -421,8 +420,8 @@ Status DeepCpuAttnLstmOp::ValidateInputs( [max_memory_step](int len) { return len <= 0 || len > max_memory_step; }); if (item_not_in_range != mem_seq_lens_span.cend()) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Attention mechanism memory sequence lengths value must in (0, ", - max_memory_step, "], while ", *item_not_in_range, " found!"); + "Attention mechanism memory sequence lengths value must in (0, ", + max_memory_step, "], while ", *item_not_in_range, " found!"); } } @@ -432,8 +431,8 @@ Status DeepCpuAttnLstmOp::ValidateInputs( memory_layer_shape[0] != num_directions_ || memory_layer_shape[1] != memory_depth) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Attention memory layer weight shape error! Expected:{", - num_directions_, ",", memory_depth, ", am_attn_size}, Got:", memory_layer_shape); + "Attention memory layer weight shape error! Expected:{", + num_directions_, ",", memory_depth, ", am_attn_size}, Got:", memory_layer_shape); } const int am_attn_size = gsl::narrow(memory_layer_shape[2]); @@ -444,8 +443,8 @@ Status DeepCpuAttnLstmOp::ValidateInputs( query_layer_shape[1] != hidden_size_ || query_layer_shape[2] != am_attn_size) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Attention query layer weight shape error! Expected:{", - num_directions_, ", ", hidden_size_, ", ", am_attn_size, "}, Got: ", query_layer_shape); + "Attention query layer weight shape error! Expected:{", + num_directions_, ", ", hidden_size_, ", ", am_attn_size, "}, Got: ", query_layer_shape); } // check attention v for [num_directions, am_attn_size] @@ -454,8 +453,8 @@ Status DeepCpuAttnLstmOp::ValidateInputs( v_shape[0] != num_directions_ || v_shape[1] != am_attn_size) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Attention v weight shape error! Expected:{", num_directions_, ", ", am_attn_size, - "}. Got: ", v_shape); + "Attention v weight shape error! Expected:{", num_directions_, ", ", am_attn_size, + "}. Got: ", v_shape); } // Check attention layer weights for [num_directions, memory_depth+cell_hidden_size, aw_attn_size] @@ -467,8 +466,8 @@ Status DeepCpuAttnLstmOp::ValidateInputs( attn_layer_shape[0] != num_directions_ || attn_layer_shape[1] != memory_depth + hidden_size_) { return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, - "Attention layer weight shape error! Expected: {", num_directions_, ", ", - memory_depth + hidden_size_, ", aw_attn_size}. Got:", attn_layer_shape); + "Attention layer weight shape error! Expected: {", num_directions_, ", ", + memory_depth + hidden_size_, ", aw_attn_size}. Got:", attn_layer_shape); } aw_attn_size = gsl::narrow(attn_layer_shape[2]); } @@ -486,7 +485,7 @@ Status DeepCpuAttnLstmOp::ValidateInputs( initial_c_shape[2] != hidden_size_) return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Input initial_c must have shape {", - num_directions_, ",", batch_size, ",", hidden_size_, "}. Actual:", initial_c_shape); + num_directions_, ",", batch_size, ",", hidden_size_, "}. Actual:", initial_c_shape); } if (P != nullptr) { @@ -497,7 +496,7 @@ Status DeepCpuAttnLstmOp::ValidateInputs( p_shape[1] != 3 * hidden_size_) return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Input P must have shape {", - num_directions_, ",", 3 * hidden_size_, "}. Actual:", p_shape); + num_directions_, ",", 3 * hidden_size_, "}. Actual:", p_shape); } return Status::OK(); diff --git a/onnxruntime/contrib_ops/cpu/attnlstm/deep_cpu_attn_lstm.h b/onnxruntime/contrib_ops/cpu/attnlstm/deep_cpu_attn_lstm.h index 4ed92c9089..085fab4bfb 100644 --- a/onnxruntime/contrib_ops/cpu/attnlstm/deep_cpu_attn_lstm.h +++ b/onnxruntime/contrib_ops/cpu/attnlstm/deep_cpu_attn_lstm.h @@ -8,7 +8,6 @@ #include "attention_wrapper.h" #include "core/framework/op_kernel.h" -#include "core/common/task_thread_pool.h" #include "core/providers/cpu/rnn/rnn_helpers.h" namespace onnxruntime { @@ -93,11 +92,15 @@ class DeepCpuAttnLstmOp final : public OpKernel { ActivationFuncs activation_funcs_; - // Threadpool for operator. If concurrent Compute calls are possible, it will be shared - // across them. mutable due to this. - // The alternative would be to create a threadpool in each call to Compute but that would incur thread creation - // cost on every call. +// Threadpool for operator. If concurrent Compute calls are possible, it will be shared +// across them. mutable due to this. +// The alternative would be to create a threadpool in each call to Compute but that would incur thread creation +// cost on every call. +#ifdef USE_EIGEN_THREADPOOL + mutable Eigen::NonBlockingThreadPool ttp_{static_cast(std::thread::hardware_concurrency())}; +#else mutable TaskThreadPool ttp_{std::thread::hardware_concurrency()}; +#endif }; } // namespace contrib diff --git a/onnxruntime/contrib_ops/cpu/attnlstm/uni_dir_attn_lstm.cc b/onnxruntime/contrib_ops/cpu/attnlstm/uni_dir_attn_lstm.cc index c9201e8913..7b90d14ae1 100644 --- a/onnxruntime/contrib_ops/cpu/attnlstm/uni_dir_attn_lstm.cc +++ b/onnxruntime/contrib_ops/cpu/attnlstm/uni_dir_attn_lstm.cc @@ -45,7 +45,11 @@ UniDirectionalAttnLstm::UniDirectionalAttnLstm(AllocatorPtr allocator, const ActivationFuncs::Entry& activation_func_g, const ActivationFuncs::Entry& activation_func_h, const float clip, +#ifdef USE_EIGEN_THREADPOOL + Eigen::NonBlockingThreadPool& ttp) +#else TaskThreadPool& ttp) +#endif : allocator_(allocator), logger_(logger), seq_length_(seq_length), diff --git a/onnxruntime/contrib_ops/cpu/attnlstm/uni_dir_attn_lstm.h b/onnxruntime/contrib_ops/cpu/attnlstm/uni_dir_attn_lstm.h index be82163bba..d7c539125c 100644 --- a/onnxruntime/contrib_ops/cpu/attnlstm/uni_dir_attn_lstm.h +++ b/onnxruntime/contrib_ops/cpu/attnlstm/uni_dir_attn_lstm.h @@ -9,7 +9,6 @@ #include "core/common/common.h" #include "core/common/logging/logging.h" -#include "core/common/task_thread_pool.h" #include "core/framework/allocator.h" #include @@ -22,7 +21,6 @@ namespace logging = ::onnxruntime::logging; using ::onnxruntime::AllocatorPtr; using ::onnxruntime::IAllocatorUniquePtr; -using ::onnxruntime::TaskThreadPool; using ::onnxruntime::contrib::detail::ActivationInfo; using ::onnxruntime::rnn::detail::ActivationFuncs; using ::onnxruntime::rnn::detail::Direction; @@ -53,7 +51,11 @@ class UniDirectionalAttnLstm { const ActivationFuncs::Entry& activation_func_g, const ActivationFuncs::Entry& activation_func_h, const float clip, +#ifdef USE_EIGEN_THREADPOOL + Eigen::NonBlockingThreadPool& ttp); +#else TaskThreadPool& ttp); +#endif void Compute(const gsl::span& inputs, const gsl::span& sequence_lengths, @@ -153,7 +155,11 @@ class UniDirectionalAttnLstm { AttentionWrapper& attention_wrapper_; +#ifdef USE_EIGEN_THREADPOOL + Eigen::NonBlockingThreadPool& ttp_; +#else TaskThreadPool& ttp_; +#endif }; } // namespace detail diff --git a/onnxruntime/core/framework/parallel_executor.cc b/onnxruntime/core/framework/parallel_executor.cc index a8033948ae..ad9596f5e5 100644 --- a/onnxruntime/core/framework/parallel_executor.cc +++ b/onnxruntime/core/framework/parallel_executor.cc @@ -9,7 +9,11 @@ #include #include "core/common/common.h" #include "core/common/logging/logging.h" + +#ifndef USE_EIGEN_THREADPOOL #include "core/common/task_thread_pool.h" +#endif + #include "core/framework/allocation_planner.h" #include "core/framework/execution_frame.h" #include "core/framework/session_state.h" @@ -238,9 +242,19 @@ void ParallelExecutor::EnqueueNode(size_t p_node_index, const SessionState& sess std::unique_lock lock(complete_mutex_); out_standings_++; } - //std::cout << "Enqueue async node: " << p_node_index << ", out_standings: " << out_standings_ << std::endl; + +#ifdef USE_EIGEN_THREADPOOL + session_state.GetThreadPool()->Schedule([this, p_node_index, &session_state, &logger]() { + try { + ParallelExecutor::RunNodeAsync(p_node_index, std::cref(session_state), std::cref(logger)); + } catch (...) { + // catch node processing failure exceptions here to prevent app crash. + } + }); +#else std::packaged_task task{std::bind(&ParallelExecutor::RunNodeAsync, this, p_node_index, std::cref(session_state), std::cref(logger))}; session_state.GetThreadPool()->RunTask(std::move(task)); +#endif } Status ParallelExecutor::FetchOutput(const MLValueNameIdxMap& name_idx_map, diff --git a/onnxruntime/core/framework/session_state.h b/onnxruntime/core/framework/session_state.h index b526e398cd..a855e0741a 100644 --- a/onnxruntime/core/framework/session_state.h +++ b/onnxruntime/core/framework/session_state.h @@ -21,15 +21,22 @@ #include "core/graph/graph_viewer.h" #include "core/framework/fuse_nodes_funcs.h" +#ifdef USE_EIGEN_THREADPOOL +#include +#endif + namespace onnxruntime { class ExecutionProviders; class KernelDef; class OpKernel; -class TaskThreadPool; struct SequentialExecutionPlan; struct MemoryPatternGroup; +#ifndef USE_EIGEN_THREADPOOL +class TaskThreadPool; +#endif + // SessionState should be modified by the inference session class only. // It is supposed to be passed by const-ref only to all the executors. class SessionState { @@ -146,8 +153,13 @@ class SessionState { /// Return SessionState for the given Node index and attribute name if found. const SessionState* GetSubgraphSessionState(onnxruntime::NodeIndex index, const std::string& attribute_name) const; +#ifdef USE_EIGEN_THREADPOOL + Eigen::NonBlockingThreadPool* GetThreadPool() const { return thread_pool_; } + void SetThreadPool(Eigen::NonBlockingThreadPool* p_pool) { thread_pool_ = p_pool; } +#else TaskThreadPool* GetThreadPool() const { return thread_pool_; } void SetThreadPool(TaskThreadPool* p_pool) { thread_pool_ = p_pool; } +#endif bool ExportDll() const { return export_fused_dll_; } void SetExportDllFlag(bool flag) { export_fused_dll_ = flag; } @@ -187,7 +199,12 @@ class SessionState { std::unordered_map>>; SubgraphSessionStateMap subgraph_session_states_; + +#ifdef USE_EIGEN_THREADPOOL + Eigen::NonBlockingThreadPool* thread_pool_ = nullptr; +#else TaskThreadPool* thread_pool_ = nullptr; +#endif bool export_fused_dll_ = false; FuncManager fused_funcs_mgr_; diff --git a/onnxruntime/core/platform/windows/debug_alloc.cc b/onnxruntime/core/platform/windows/debug_alloc.cc index ec9febb37b..e454d4447c 100644 --- a/onnxruntime/core/platform/windows/debug_alloc.cc +++ b/onnxruntime/core/platform/windows/debug_alloc.cc @@ -231,11 +231,7 @@ Memory_LeakCheck::~Memory_LeakCheck() { else { // If we're on the command line (like on a build machine), output to the console and exit(-1) std::cout << "\n----- MEMORY LEAKS: " << string.c_str() << "\n"; -#if 0 - // There is currently a memory leak due to a static thread_local variable not being destroyed on exit in mkldnn_common.h - // The bug is caused by sync_api.h using the windows thread pool functions instead of C++ std::async libraries. exit(-1); -#endif } } else { diff --git a/onnxruntime/core/providers/cpu/rnn/deep_cpu_gru.cc b/onnxruntime/core/providers/cpu/rnn/deep_cpu_gru.cc index 311844b89e..3bb5487f9b 100644 --- a/onnxruntime/core/providers/cpu/rnn/deep_cpu_gru.cc +++ b/onnxruntime/core/providers/cpu/rnn/deep_cpu_gru.cc @@ -177,7 +177,11 @@ class UniDirectionalGru { const ActivationFuncs::Entry& activation_func_f, const ActivationFuncs::Entry& activation_func_g, const float clip, - TaskThreadPool& ttp); +#ifdef USE_EIGEN_THREADPOOL + Eigen::NonBlockingThreadPool& ttp_); +#else + TaskThreadPool& ttp_); +#endif void Compute(const gsl::span& inputs, const gsl::span& sequence_lengths, @@ -192,7 +196,12 @@ class UniDirectionalGru { private: AllocatorPtr allocator_; const logging::Logger& logger_; + +#ifdef USE_EIGEN_THREADPOOL + Eigen::NonBlockingThreadPool& ttp_; +#else TaskThreadPool& ttp_; +#endif int seq_length_; int batch_size_; @@ -375,9 +384,14 @@ Status DeepCpuGruOp::ComputeImpl(OpKernelContext& context) const { hidden_output_size_per_direction); #ifndef USE_MKLDNN + +#ifdef USE_EIGEN_THREADPOOL + auto fn = +#else std::packaged_task task_fw{ +#endif [&]() { -#endif // ! USE_MKLDNN +#endif // ! USE_MKLDNN std::unique_ptr> fw = std::make_unique>( alloc, logger, seq_length, batch_size, input_size, hidden_size_, linear_before_reset_, Direction::kForward, @@ -387,43 +401,67 @@ Status DeepCpuGruOp::ComputeImpl(OpKernelContext& context) const { clip_, ttp_); fw->Compute(input, sequence_lens_span, num_directions_, input_weights_1, recurrent_weights_1, output_1, hidden_output_1); #ifndef USE_MKLDNN - }}; - auto task_results_fw = task_fw.get_future(); - ttp_.RunTask(std::move(task_fw)); -#endif // ! USE_MKLDNN - std::unique_ptr> bw = std::make_unique>( - alloc, logger, - seq_length, batch_size, input_size, hidden_size_, linear_before_reset_, Direction::kReverse, - bias_2, initial_hidden_2, - activation_funcs_.Entries()[2], - activation_funcs_.Entries()[3], - clip_, ttp_); - bw->Compute(input, sequence_lens_span, num_directions_, input_weights_2, recurrent_weights_2, output_2, hidden_output_2); +#ifndef USE_EIGEN_THREADPOOL + } + }; + auto task_results_fw = task_fw.get_future(); + ttp_.RunTask(std::move(task_fw)); +#else + }; + std::condition_variable cv; + std::mutex lock; + bool done = false; + + ttp_.Schedule([&]() { + fn(); + auto ul = std::unique_lock(lock); + done = true; + cv.notify_one(); + }); +#endif // USE_EIGEN_THREADPOOL + +#endif // ! USE_MKLDNN + + std::unique_ptr> bw = std::make_unique>( + alloc, logger, + seq_length, batch_size, input_size, hidden_size_, linear_before_reset_, Direction::kReverse, + bias_2, initial_hidden_2, + activation_funcs_.Entries()[2], + activation_funcs_.Entries()[3], + clip_, ttp_); + bw->Compute(input, sequence_lens_span, num_directions_, input_weights_2, recurrent_weights_2, output_2, hidden_output_2); #ifndef USE_MKLDNN +#ifdef USE_EIGEN_THREADPOOL + auto ul = std::unique_lock(lock); + if (!done) cv.wait(ul); +#else task_results_fw.get(); -#endif // ! USE_MKLDNN - } else { - std::unique_ptr> gru_p = std::make_unique>( - alloc, logger, - seq_length, batch_size, input_size, hidden_size_, linear_before_reset_, direction_, - bias_1, initial_hidden_1, - activation_funcs_.Entries()[0], - activation_funcs_.Entries()[1], - clip_, ttp_); +#endif - gru_p->Compute(input, sequence_lens_span, num_directions_, input_weights_1, recurrent_weights_1, output_1, hidden_output_1); - } +#endif // ! USE_MKLDNN +} // namespace onnxruntime +else { + std::unique_ptr> gru_p = std::make_unique>( + alloc, logger, + seq_length, batch_size, input_size, hidden_size_, linear_before_reset_, direction_, + bias_1, initial_hidden_1, + activation_funcs_.Entries()[0], + activation_funcs_.Entries()[1], + clip_, ttp_); - if (!output.empty()) - DumpMatrix("Y", output.data(), seq_length * num_directions_ * batch_size, hidden_size_); - - DumpMatrix("Y_h", hidden_output.data(), num_directions_ * batch_size, hidden_size_); - - return Status::OK(); + gru_p->Compute(input, sequence_lens_span, num_directions_, input_weights_1, recurrent_weights_1, output_1, hidden_output_1); } +if (!output.empty()) + DumpMatrix("Y", output.data(), seq_length* num_directions_* batch_size, hidden_size_); + +DumpMatrix("Y_h", hidden_output.data(), num_directions_* batch_size, hidden_size_); + +return Status::OK(); +} // namespace onnxruntime + // // Implementation of internal helper code namespace detail { @@ -442,7 +480,11 @@ UniDirectionalGru::UniDirectionalGru(AllocatorPtr allocator, const ActivationFuncs::Entry& activation_func_f, const ActivationFuncs::Entry& activation_func_g, const float clip, +#ifdef USE_EIGEN_THREADPOOL + Eigen::NonBlockingThreadPool& ttp) +#else TaskThreadPool& ttp) +#endif : allocator_(allocator), logger_(logger), ttp_(ttp), @@ -490,8 +532,8 @@ UniDirectionalGru::UniDirectionalGru(AllocatorPtr allocator, // replicate what we just wrote to the start of the output span so we have batch_size_ copies auto values = output.cbegin(); ORT_IGNORE_RETURN_VALUE(RepeatVectorToConstructArray(values, values + hidden_size_, - output.begin() + hidden_size_, // skip the first batch - batch_size_ - 1)); // and replicate batch size - 1 times + output.begin() + hidden_size_, // skip the first batch + batch_size_ - 1)); // and replicate batch size - 1 times }; // we can always combine the z and r weights @@ -603,7 +645,7 @@ void UniDirectionalGru::Compute(const gsl::span& inputs_arg, if (batch_size_ % hidden_num_threads_ != 0) fused_hidden_rows++; - // lambda executed by TaskThreadPool + // lambda executed by Eigen::NonBlockingThreadPool auto hidden_gemm_and_activations = [&](const int row) { //handling boundaries int local_fused_hidden_rows = fused_hidden_rows; @@ -815,8 +857,7 @@ void UniDirectionalGru::Compute(const gsl::span& inputs_arg, } }; - ExecuteLambdaInParallel("Processing batch", hidden_gemm_and_activations, batch_size_, fused_hidden_rows, - ttp_, logger_); + ExecuteLambdaInParallel("Processing batch", hidden_gemm_and_activations, batch_size_, fused_hidden_rows, ttp_, logger_); } else { size_t out_added_offset; diff --git a/onnxruntime/core/providers/cpu/rnn/deep_cpu_gru.h b/onnxruntime/core/providers/cpu/rnn/deep_cpu_gru.h index cef9b6452a..e44c4175d0 100644 --- a/onnxruntime/core/providers/cpu/rnn/deep_cpu_gru.h +++ b/onnxruntime/core/providers/cpu/rnn/deep_cpu_gru.h @@ -5,7 +5,6 @@ #include -#include "core/common/task_thread_pool.h" #include "core/framework/allocator.h" #include "core/framework/op_kernel.h" #include "core/providers/cpu/rnn/rnn_helpers.h" @@ -71,7 +70,11 @@ class DeepCpuGruOp final : public OpKernel { // across them. mutable due to this. // The alternative would be to create a threadpool in each call to Compute but that would incur thread creation // cost on every call. +#ifdef USE_EIGEN_THREADPOOL + mutable Eigen::NonBlockingThreadPool ttp_{static_cast(std::thread::hardware_concurrency())}; +#else mutable TaskThreadPool ttp_{std::thread::hardware_concurrency()}; +#endif template Status ComputeImpl(OpKernelContext& context) const; diff --git a/onnxruntime/core/providers/cpu/rnn/deep_cpu_lstm.cc b/onnxruntime/core/providers/cpu/rnn/deep_cpu_lstm.cc index 06560b72cf..4e1ed72292 100644 --- a/onnxruntime/core/providers/cpu/rnn/deep_cpu_lstm.cc +++ b/onnxruntime/core/providers/cpu/rnn/deep_cpu_lstm.cc @@ -13,7 +13,6 @@ #include "core/common/common.h" #include "core/common/logging/logging.h" -#include "core/common/task_thread_pool.h" #include "core/framework/allocator.h" #ifdef _MSC_VER @@ -204,7 +203,11 @@ class UniDirectionalLstm { const ActivationFuncs::Entry& activation_func_g, const ActivationFuncs::Entry& activation_func_h, const float clip, +#ifdef USE_EIGEN_THREADPOOL + Eigen::NonBlockingThreadPool& ttp); +#else TaskThreadPool& ttp); +#endif void Compute(const gsl::span& inputs, const gsl::span& sequence_lengths, @@ -296,7 +299,11 @@ class UniDirectionalLstm { ActivationInfo activation_g_; ActivationInfo activation_h_; +#ifdef USE_EIGEN_THREADPOOL + Eigen::NonBlockingThreadPool& ttp_; +#else TaskThreadPool& ttp_; +#endif }; } // namespace detail @@ -518,7 +525,7 @@ Status DeepCpuLstmOp::ValidateInputs(const Tensor& X, const Tensor& W, const Ten initial_c_shape[2] != hidden_size_) return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Input initial_c must have shape {", - num_directions_, ",", batch_size, ",", hidden_size_, "}. Actual:", initial_c_shape); + num_directions_, ",", batch_size, ",", hidden_size_, "}. Actual:", initial_c_shape); } if (P != nullptr) { @@ -529,7 +536,7 @@ Status DeepCpuLstmOp::ValidateInputs(const Tensor& X, const Tensor& W, const Ten p_shape[1] != 3 * hidden_size_) return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Input P must have shape {", - num_directions_, ",", 3 * hidden_size_, "}. Actual:", p_shape); + num_directions_, ",", 3 * hidden_size_, "}. Actual:", p_shape); } return Status::OK(); @@ -559,7 +566,11 @@ UniDirectionalLstm::UniDirectionalLstm(AllocatorPtr allocator, const ActivationFuncs::Entry& activation_func_g, const ActivationFuncs::Entry& activation_func_h, const float clip, +#ifdef USE_EIGEN_THREADPOOL + Eigen::NonBlockingThreadPool& ttp) +#else TaskThreadPool& ttp) +#endif : allocator_(allocator), logger_(logger), seq_length_(seq_length), @@ -882,8 +893,7 @@ void UniDirectionalLstm::Compute(const gsl::span& inputs_arg, } }; - ExecuteLambdaInParallel("Processing batch", hidden_gemm_and_activations, batch_size_, fused_hidden_rows, - ttp_, logger_); + ExecuteLambdaInParallel("Processing batch", hidden_gemm_and_activations, batch_size_, fused_hidden_rows, ttp_, logger_); } else { span_T_iter c_prev = batched_internal_state_prev_one_step.begin(); diff --git a/onnxruntime/core/providers/cpu/rnn/deep_cpu_lstm.h b/onnxruntime/core/providers/cpu/rnn/deep_cpu_lstm.h index 3d2b186de9..eeafad1a10 100644 --- a/onnxruntime/core/providers/cpu/rnn/deep_cpu_lstm.h +++ b/onnxruntime/core/providers/cpu/rnn/deep_cpu_lstm.h @@ -6,9 +6,12 @@ #include #include "core/framework/op_kernel.h" -#include "core/common/task_thread_pool.h" #include "core/providers/cpu/rnn/rnn_helpers.h" +#ifndef USE_EIGEN_THREADPOOL +#include "core/common/task_thread_pool.h" +#endif + namespace onnxruntime { /// The class represents DeepCPU implementation of a long short term memory (LSTM) operator. @@ -82,7 +85,12 @@ class DeepCpuLstmOp final : public OpKernel { // across them. mutable due to this. // The alternative would be to create a threadpool in each call to Compute but that would incur thread creation // cost on every call. + +#ifdef USE_EIGEN_THREADPOOL + mutable Eigen::NonBlockingThreadPool ttp_{static_cast(std::thread::hardware_concurrency())}; +#else mutable TaskThreadPool ttp_{std::thread::hardware_concurrency()}; +#endif }; } // namespace onnxruntime diff --git a/onnxruntime/core/providers/cpu/rnn/rnn_helpers.h b/onnxruntime/core/providers/cpu/rnn/rnn_helpers.h index 6d779ded23..f30ea044a7 100644 --- a/onnxruntime/core/providers/cpu/rnn/rnn_helpers.h +++ b/onnxruntime/core/providers/cpu/rnn/rnn_helpers.h @@ -3,6 +3,10 @@ #pragma once +#ifdef _WIN32 +#pragma warning(disable : 4267) +#endif + #include #include #include @@ -13,12 +17,17 @@ #include "gsl/gsl_algorithm" #include "core/common/common.h" -#include "core/common/task_thread_pool.h" #include "core/common/logging/logging.h" #include "core/framework/allocator.h" #include "core/util/math.h" #include "core/util/math_cpuonly.h" +#ifdef USE_EIGEN_THREADPOOL +#include +#else +#include "core/common/task_thread_pool.h" +#endif + namespace onnxruntime { class Tensor; class OpKernelContext; @@ -209,7 +218,12 @@ T* SafeRawPointer(typename gsl::span span, size_t offset, size_t size) { template void ExecuteLambdaInParallel(const std::string& name, TLambda lambda, int max, int step, - TaskThreadPool& ttp, const ::onnxruntime::logging::Logger& logger) { +#ifdef USE_EIGEN_THREADPOOL + Eigen::NonBlockingThreadPool& ttp, +#else + TaskThreadPool& ttp, +#endif + const ::onnxruntime::logging::Logger& logger) { // #define NOTHREADS to execute the lambdas directly and in order if you need to do that to debug #ifdef NOTHREADS @@ -221,6 +235,23 @@ void ExecuteLambdaInParallel(const std::string& name, TLambda lambda, int max, i std::bind(lambda, i)(); } #else + +#ifdef USE_EIGEN_THREADPOOL + ORT_UNUSED_PARAMETER(name); + ORT_UNUSED_PARAMETER(logger); + + std::atomic done(0); + for (int i = 0; i < max; i += step) { + ttp.Schedule([lambda, i, &done]() { + lambda(i); + ++done; + }); + } + + int totalTasks = (int)max / (step > 0 ? step : 1) + (max % step > 0 ? 1 : 0); + while (done != totalTasks) { + } +#else std::vector > task_results{}; task_results.reserve(static_cast(std::ceil(max / step))); @@ -229,7 +260,6 @@ void ExecuteLambdaInParallel(const std::string& name, TLambda lambda, int max, i task_results.emplace_back(task.get_future()); ttp.RunTask(std::move(task)); } - try { // wait for all and propagate any exceptions for (auto& future : task_results) @@ -238,7 +268,8 @@ void ExecuteLambdaInParallel(const std::string& name, TLambda lambda, int max, i LOGS(logger, ERROR) << name << " - exception running tasks: " << ex.what(); throw; } -#endif +#endif // else part of #ifdef USE_EIGEN_THREADPOOLs +#endif // else part of #ifdef NOTHREADS } void DumpMatrixImpl(const std::string& name, const float* src, int row, int col, diff --git a/onnxruntime/core/session/inference_session.cc b/onnxruntime/core/session/inference_session.cc index 3894954217..cc90cd5e57 100644 --- a/onnxruntime/core/session/inference_session.cc +++ b/onnxruntime/core/session/inference_session.cc @@ -1,6 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +#ifdef _WIN32 +#pragma warning(disable : 4267) +#endif + #include "core/session/inference_session.h" #include @@ -40,6 +44,10 @@ #include "core/session/CustomOpsLoader.h" #include "core/session/IOBinding.h" +#ifdef USE_EIGEN_THREADPOOL +#include +#endif + using namespace ONNX_NAMESPACE; namespace onnxruntime { @@ -63,7 +71,12 @@ class InferenceSession::Impl { int pool_size = session_options_.session_thread_pool_size == 0 ? std::thread::hardware_concurrency() / 2 : session_options_.session_thread_pool_size; + +#ifdef USE_EIGEN_THREADPOOL + thread_pool_ = std::make_unique(pool_size); +#else thread_pool_ = std::make_unique(pool_size); +#endif } session_state_.SetThreadPool(thread_pool_.get()); @@ -1130,14 +1143,19 @@ class InferenceSession::Impl { // Threadpool for this session //thread::ThreadPool thread_pool_; // not used for now; will add it later when implementing RunAsync +#ifdef USE_EIGEN_THREADPOOL + std::unique_ptr thread_pool_; +#else std::unique_ptr thread_pool_; +#endif // Number of concurrently running executors - std::atomic current_num_runs_; + std::atomic + current_num_runs_; mutable onnxruntime::OrtMutex session_mutex_; // to ensure only one thread can invoke Load/Initialize - bool is_model_loaded_ = false; // GUARDED_BY(session_mutex_) - bool is_inited_ = false; // GUARDED_BY(session_mutex_) + bool is_model_loaded_ = false; // GUARDED_BY(session_mutex_) + bool is_inited_ = false; // GUARDED_BY(session_mutex_) std::map weights_buffers_; InsertCastTransformer insert_cast_transformer_; diff --git a/onnxruntime/test/onnx/onnxruntime_event.h b/onnxruntime/test/onnx/onnxruntime_event.h index ed186a4d4c..b8869c7188 100644 --- a/onnxruntime/test/onnx/onnxruntime_event.h +++ b/onnxruntime/test/onnx/onnxruntime_event.h @@ -1,14 +1,15 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +//TODO: switch to nsync mutex and cv #include -#include +#include #include struct OnnxRuntimeEvent { public: - pthread_mutex_t finish_event_mutex = PTHREAD_MUTEX_INITIALIZER; - pthread_cond_t finish_event_data = PTHREAD_COND_INITIALIZER; + std::mutex finish_event_mutex; + std::condition_variable finish_event_data; bool finished = false; OnnxRuntimeEvent() = default; diff --git a/onnxruntime/test/onnx/sync_api_linux.cc b/onnxruntime/test/onnx/sync_api.cc similarity index 66% rename from onnxruntime/test/onnx/sync_api_linux.cc rename to onnxruntime/test/onnx/sync_api.cc index 591b6c292c..5426709f42 100644 --- a/onnxruntime/test/onnx/sync_api_linux.cc +++ b/onnxruntime/test/onnx/sync_api.cc @@ -3,10 +3,13 @@ #include "sync_api.h" #include + +#if defined(_MSC_VER) +#pragma warning(disable : 4267) +#endif #include #include #include -#include "simple_thread_pool.h" #include "onnxruntime_event.h" using onnxruntime::common::Status; @@ -25,11 +28,12 @@ class OnnxRuntimeCallbackInstance { Status WaitAndCloseEvent(ORT_EVENT finish_event) { if (finish_event == nullptr) return Status(onnxruntime::common::ONNXRUNTIME, onnxruntime::common::INVALID_ARGUMENT, ""); - pthread_mutex_lock(&finish_event->finish_event_mutex); - while (!finish_event->finished) { - pthread_cond_wait(&finish_event->finish_event_data, &finish_event->finish_event_mutex); + { + std::unique_lock lock(finish_event->finish_event_mutex); + while (!finish_event->finished) { + finish_event->finish_event_data.wait(lock); + } } - pthread_mutex_unlock(&finish_event->finish_event_mutex); delete finish_event; return Status::OK(); } @@ -51,14 +55,14 @@ Status CreateAndSubmitThreadpoolWork(ORT_CALLBACK_FUNCTION callback, void* data, return Status::OK(); } -using DefaultThreadPoolType = onnxruntime::SimpleThreadPoolTempl; +using DefaultThreadPoolType = Eigen::NonBlockingThreadPool; static std::unique_ptr default_pool; static std::once_flag default_pool_init; PThreadPool GetDefaultThreadPool(const onnxruntime::Env& env) { std::call_once(default_pool_init, [&env] { int core_num = env.GetNumCpuCores(); - default_pool.reset(new DefaultThreadPoolType(core_num, env)); + default_pool.reset(new DefaultThreadPoolType(core_num)); }); return default_pool.get(); } @@ -68,16 +72,12 @@ Status OnnxRuntimeSetEventWhenCallbackReturns(ORT_CALLBACK_INSTANCE pci, ORT_EVE return Status(onnxruntime::common::ONNXRUNTIME, onnxruntime::common::INVALID_ARGUMENT, ""); if (pci == nullptr) { - if (pthread_mutex_lock(&finish_event->finish_event_mutex)) { - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "lock failed"); + { + std::unique_lock lock(finish_event->finish_event_mutex); + finish_event->finished = true; } - finish_event->finished = true; - if (pthread_mutex_unlock(&finish_event->finish_event_mutex)) - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "unlock failed"); - if (!pthread_cond_broadcast(&finish_event->finish_event_data)) - return Status::OK(); - else - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "pthread_cond_broadcast failed"); + finish_event->finish_event_data.notify_all(); + return Status::OK(); } else { pci->AddEvent(finish_event); return Status::OK(); @@ -90,14 +90,11 @@ void OnnxRuntimeCallbackInstance::AddEvent(ORT_EVENT event) { Status OnnxRuntimeCallbackInstance::SignalAllEvents() { for (ORT_EVENT finish_event : events_to_signal_) { - if (pthread_mutex_lock(&finish_event->finish_event_mutex)) { - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "lock failed"); + { + std::unique_lock lock(finish_event->finish_event_mutex); + finish_event->finished = true; } - finish_event->finished = true; - if (pthread_mutex_unlock(&finish_event->finish_event_mutex)) - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "unlock failed"); - if (pthread_cond_broadcast(&finish_event->finish_event_data)) - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "pthread_cond_broadcast failed"); + finish_event->finish_event_data.notify_all(); } return Status::OK(); } diff --git a/onnxruntime/test/onnx/sync_api.h b/onnxruntime/test/onnx/sync_api.h index 7bc8db4d1a..beab82d3be 100644 --- a/onnxruntime/test/onnx/sync_api.h +++ b/onnxruntime/test/onnx/sync_api.h @@ -3,27 +3,11 @@ #pragma once -#ifdef _WIN32 -#include -#else #include -#endif #include #include #include -#ifdef _WIN32 -using ORT_CALLBACK_INSTANCE = PTP_CALLBACK_INSTANCE; -using ORT_EVENT = HANDLE; -#define ORT_CALLBACK __stdcall -using ORT_WORK = PTP_WORK; -using PThreadPool = PTP_CALLBACK_ENVIRON; -using ORT_CALLBACK_FUNCTION = PTP_WORK_CALLBACK; -#define OnnxRuntimeCloseThreadpoolWork CloseThreadpoolWork -inline PThreadPool GetDefaultThreadPool(const ::onnxruntime::Env&) { - return nullptr; -} -#else #define ORT_CALLBACK namespace Eigen { class ThreadPoolInterface; @@ -38,7 +22,6 @@ using ORT_CALLBACK_INSTANCE = OnnxRuntimeCallbackInstance*; using ORT_CALLBACK_FUNCTION = void ORT_CALLBACK (*)(ORT_CALLBACK_INSTANCE pci, void* context, ORT_WORK work); //Do nothing inline void OnnxRuntimeCloseThreadpoolWork(ORT_WORK) {} -#endif //The returned value will be used with CreateAndSubmitThreadpoolWork function PThreadPool GetDefaultThreadPool(const ::onnxruntime::Env& env); diff --git a/onnxruntime/test/onnx/sync_api_win.cc b/onnxruntime/test/onnx/sync_api_win.cc deleted file mode 100644 index b5ce864470..0000000000 --- a/onnxruntime/test/onnx/sync_api_win.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "sync_api.h" -#include - -using ::onnxruntime::common::Status; - -Status CreateAndSubmitThreadpoolWork(ORT_CALLBACK_FUNCTION callback, void* data, PThreadPool pool) { - PTP_WORK work = CreateThreadpoolWork(callback, data, pool); - if (!work) { - return Status(::onnxruntime::common::ONNXRUNTIME, ::onnxruntime::common::FAIL, "create thread pool task failed"); - } - SubmitThreadpoolWork(work); - return Status::OK(); -} - -Status WaitAndCloseEvent(ORT_EVENT finish_event) { - DWORD dwWaitResult = WaitForSingleObject(finish_event, INFINITE); - (void)CloseHandle(finish_event); - if (dwWaitResult != WAIT_OBJECT_0) { - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "WaitForSingleObject failed"); - } - return Status::OK(); -} - -Status CreateOnnxRuntimeEvent(ORT_EVENT* out) { - if (out == nullptr) - return Status(::onnxruntime::common::ONNXRUNTIME, ::onnxruntime::common::INVALID_ARGUMENT, ""); - HANDLE finish_event = CreateEvent( - NULL, // default security attributes - TRUE, // manual-reset event - FALSE, // initial state is nonsignaled - NULL); - if (finish_event == NULL) { - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "unable to create finish event"); - } - *out = finish_event; - return Status::OK(); -} - -Status OnnxRuntimeSetEventWhenCallbackReturns(ORT_CALLBACK_INSTANCE pci, ORT_EVENT finish_event) { - if (finish_event == nullptr) - return Status(::onnxruntime::common::ONNXRUNTIME, ::onnxruntime::common::INVALID_ARGUMENT, ""); - if (pci) - SetEventWhenCallbackReturns(pci, finish_event); - else if (!SetEvent(finish_event)) { - return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "SetEvent failed"); - } - return Status::OK(); -} - -void OrtCloseEvent(ORT_EVENT finish_event) { - (void)CloseHandle(finish_event); -} diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index be32077599..9a113ec5d3 100755 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -108,6 +108,7 @@ Use the individual flags to only run the specified stages. parser.add_argument("--use_tvm", action="store_true", help="Build with tvm") parser.add_argument("--use_openmp", action='store_true', help="Build with OpenMP.") parser.add_argument("--use_llvm", action="store_true", help="Build tvm with llvm") + parser.add_argument("--use_eigenthreadpool", action="store_true", help="Build with eigenthreadpool") parser.add_argument("--enable_msinternal", action="store_true", help="Enable for Microsoft internal builds only.") parser.add_argument("--llvm_path", help="Path to llvm dir") parser.add_argument("--azure_sas_key", help="Azure storage sas key, starts with '?'") @@ -293,6 +294,7 @@ def generate_build_tree(cmake_path, source_dir, build_dir, cuda_home, cudnn_home "-Donnxruntime_ENABLE_MICROSOFT_INTERNAL=" + ("ON" if args.enable_msinternal else "OFF"), "-Donnxruntime_USE_BRAINSLICE=" + ("ON" if args.use_brainslice else "OFF"), "-Donnxruntime_USE_NUPHAR=" + ("ON" if args.use_nuphar else "OFF"), + "-Donnxruntime_USE_EIGEN_THREADPOOL=" + ("ON" if args.use_eigenthreadpool else "OFF"), ] if args.use_brainslice: bs_pkg_name = args.brain_slice_package_name.split('.', 1)