Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use a friendly enum for graph optimization level. #1586

Merged
merged 18 commits into from
Aug 15, 2019
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ static void UseApi()

// Optional : Create session options and set the graph optimization level for the session
SessionOptions options = new SessionOptions();
options.SetSessionGraphOptimizationLevel(2);
options.SetSessionGraphOptimizationLevel(GraphOptimizationLevel.ORT_ENABLE_ALL);

using (var session = new InferenceSession(modelPath, options))
{
Expand Down
2 changes: 1 addition & 1 deletion csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ IntPtr[] outputValues /* An array of output value pointers. Array must be alloca
public static extern IntPtr /*(OrtStatus*)*/ OrtSetSessionThreadPoolSize(IntPtr /* OrtSessionOptions* */ options, int sessionThreadPoolSize);

[DllImport(nativeLib, CharSet = charSet)]
public static extern IntPtr /*(OrtStatus*)*/ OrtSetSessionGraphOptimizationLevel(IntPtr /* OrtSessionOptions* */ options, uint graphOptimizationLevel);
public static extern IntPtr /*(OrtStatus*)*/ OrtSetSessionGraphOptimizationLevel(IntPtr /* OrtSessionOptions* */ options, GraphOptimizationLevel graphOptimizationLevel);


///**
Expand Down
28 changes: 17 additions & 11 deletions csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,20 @@

namespace Microsoft.ML.OnnxRuntime
{
/// <summary>
/// TODO Add documentation about which optimizations are enabled for each value.
/// </summary>
public enum GraphOptimizationLevel
{
ORT_DISABLE_ALL = 0,
ORT_ENABLE_BASIC = 1,
ORT_ENABLE_ALL = 2
}

/// <summary>
/// Holds the options for creating an InferenceSession
/// </summary>
public class SessionOptions:IDisposable
public class SessionOptions : IDisposable
{
public IntPtr _nativePtr;
protected static readonly Lazy<SessionOptions> _default = new Lazy<SessionOptions>(MakeSessionOptionWithCpuProvider);
Expand All @@ -28,11 +38,7 @@ public SessionOptions()
/// Sets the graph optimization level for the session. Default is set to 1.
/// </summary>
/// <param name="optimization_level">optimization level for the session</param>
/// Available options are : 0, 1, 2
/// 0 -> Disable all optimizations
/// 1 -> Enable basic optimizations
/// 2 -> Enable all optimizations
public void SetSessionGraphOptimizationLevel(uint optimization_level)
public void SetSessionGraphOptimizationLevel(GraphOptimizationLevel optimization_level)
{
NativeApiStatus.VerifySuccess(NativeMethods.OrtSetSessionGraphOptimizationLevel(_nativePtr, optimization_level));
}
Expand Down Expand Up @@ -106,7 +112,7 @@ public static SessionOptions MakeSessionOptionWithCudaProvider()
/// </summary>
/// <param name="deviceId"></param>
/// <returns>A SessionsOptions() object configured for execution on deviceId</returns>
public static SessionOptions MakeSessionOptionWithCudaProvider(int deviceId=0)
public static SessionOptions MakeSessionOptionWithCudaProvider(int deviceId = 0)
{
CheckLibcVersionGreaterThanMinimum();
CheckCudaExecutionProviderDLLs();
Expand All @@ -130,16 +136,16 @@ private static bool CheckCudaExecutionProviderDLLs()
{
IntPtr handle = LoadLibrary(dll);
if (handle != IntPtr.Zero)
continue;
continue;
var sysdir = new StringBuilder(String.Empty, 2048);
GetSystemDirectory(sysdir, (uint)sysdir.Capacity);
throw new OnnxRuntimeException(
ErrorCode.NoSuchFile,
ErrorCode.NoSuchFile,
$"kernel32.LoadLibrary():'{dll}' not found. CUDA is required for GPU execution. " +
$". Verify it is available in the system directory={sysdir}. Else copy it to the output folder."
);
);
}
}
}
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,7 @@ int main(int argc, char* argv[]) {
OrtSetSessionThreadPoolSize(session_options, 1);

// Sets graph optimization level
// Available levels are
// 0 -> To disable all optimizations
// 1 -> To enable basic optimizations (Such as redundant node removals)
// 2 -> To enable all optimizations (Includes level 1 + more complex optimizations like node fusions)
OrtSetSessionGraphOptimizationLevel(session_options, 1);
OrtSetSessionGraphOptimizationLevel(session_options, ORT_ENABLE_BASIC);

// Optionally add more execution providers via session_options
// E.g. for CUDA include cuda_provider_factory.h and uncomment the following line:
Expand Down
10 changes: 5 additions & 5 deletions csharp/test/Microsoft.ML.OnnxRuntime.Tests/InferenceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ public void CanCreateAndDisposeSessionWithModelPath()
}

[Theory]
[InlineData(0, true)]
[InlineData(0, false)]
[InlineData(2, true)]
[InlineData(2, false)]
private void CanRunInferenceOnAModel(uint graphOptimizationLevel, bool disableSequentialExecution)
[InlineData(GraphOptimizationLevel.ORT_DISABLE_ALL, true)]
[InlineData(GraphOptimizationLevel.ORT_DISABLE_ALL, false)]
[InlineData(GraphOptimizationLevel.ORT_ENABLE_ALL, true)]
[InlineData(GraphOptimizationLevel.ORT_ENABLE_ALL, false)]
private void CanRunInferenceOnAModel(GraphOptimizationLevel graphOptimizationLevel, bool disableSequentialExecution)
{
string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "squeezenet.onnx");

Expand Down
17 changes: 9 additions & 8 deletions csharp/tools/Microsoft.ML.OnnxRuntime.PerfTool/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class CommandOptions
public bool ParallelExecution { get; set; } = false;

[Option('o', "optimization_level", Required = false, HelpText = "Optimization Level. Default is 1, partial optimization.")]
public uint OptimizationLevel { get; set; } = 1;
public GraphOptimizationLevel OptimizationLevel { get; set; } = GraphOptimizationLevel.ORT_ENABLE_BASIC;
}

class Program
Expand All @@ -42,7 +42,8 @@ public static void Main(string[] args)
{
var cmdOptions = Parser.Default.ParseArguments<CommandOptions>(args);
cmdOptions.WithParsed(
options => {
options =>
{
Run(options);
});
}
Expand All @@ -52,7 +53,7 @@ public static void Run(CommandOptions options)
string inputPath = options.InputFile;
int iteration = options.IterationCount;
bool parallelExecution = options.ParallelExecution;
uint optLevel = options.OptimizationLevel;
GraphOptimizationLevel optLevel = options.OptimizationLevel;
Console.WriteLine("Running model {0} in OnnxRuntime:", modelPath);
Console.WriteLine("input:{0}", inputPath);
Console.WriteLine("iteration count:{0}", iteration);
Expand Down Expand Up @@ -84,11 +85,11 @@ public static float[] LoadTensorFromFile(string filename)
return tensorData.ToArray();
}

static void RunModelOnnxRuntime(string modelPath, string inputPath, int iteration, DateTime[] timestamps, bool parallelExecution, uint optLevel)
static void RunModelOnnxRuntime(string modelPath, string inputPath, int iteration, DateTime[] timestamps, bool parallelExecution, GraphOptimizationLevel optLevel)
{
if (timestamps.Length != (int)TimingPoint.TotalCount)
{
throw new ArgumentException("Timestamps array must have "+(int)TimingPoint.TotalCount+" size");
throw new ArgumentException("Timestamps array must have " + (int)TimingPoint.TotalCount + " size");
}

timestamps[(int)TimingPoint.Start] = DateTime.Now;
Expand All @@ -108,12 +109,12 @@ static void RunModelOnnxRuntime(string modelPath, string inputPath, int iteratio
container.Add(NamedOnnxValue.CreateFromTensor<float>(name, tensor));
}



timestamps[(int)TimingPoint.InputLoaded] = DateTime.Now;

// Run the inference
for (int i=0; i < iteration; i++)
for (int i = 0; i < iteration; i++)
{
var results = session.Run(container); // results is an IReadOnlyList<NamedOnnxValue> container
Debug.Assert(results != null);
Expand All @@ -132,7 +133,7 @@ static void RunModelOnnxRuntime(string modelPath, string inputPath, int iteratio
static void PrintUsage()
{
Console.WriteLine("Usage:\n"
+"dotnet Microsoft.ML.OnnxRuntime.PerfTool <onnx-model-path> <input-file-path> <iteration-count>"
+ "dotnet Microsoft.ML.OnnxRuntime.PerfTool <onnx-model-path> <input-file-path> <iteration-count>"
);
}

Expand Down
13 changes: 8 additions & 5 deletions include/onnxruntime/core/session/onnxruntime_c_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,14 @@ ORT_API_STATUS(OrtSetSessionLogId, _Inout_ OrtSessionOptions* options, const cha
ORT_API_STATUS(OrtSetSessionLogVerbosityLevel, _Inout_ OrtSessionOptions* options, int session_log_verbosity_level);

// Set Graph optimization level.
// Available options are : 0, 1, 2.
// 0 -> Disable all optimizations
// 1 -> Enable basic optimizations
// 2 -> Enable all optimizations
ORT_API_STATUS(OrtSetSessionGraphOptimizationLevel, _Inout_ OrtSessionOptions* options, int graph_optimization_level);
// TODO Add documentation about which optimizations are enabled for each value.
typedef enum GraphOptimizationLevel {
ORT_DISABLE_ALL = 0,
ORT_ENABLE_BASIC = 1,
ORT_ENABLE_ALL = 2
} GraphOptimizationLevel;
ORT_API_STATUS(OrtSetSessionGraphOptimizationLevel, _Inout_ OrtSessionOptions* options,
GraphOptimizationLevel graph_optimization_level);

// How many threads in the session thread pool.
ORT_API_STATUS(OrtSetSessionThreadPoolSize, _Inout_ OrtSessionOptions* options, int session_thread_pool_size);
Expand Down
2 changes: 1 addition & 1 deletion include/onnxruntime/core/session/onnxruntime_cxx_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ struct SessionOptions : Base<OrtSessionOptions> {
SessionOptions Clone() const;

SessionOptions& SetThreadPoolSize(int session_thread_pool_size);
SessionOptions& SetGraphOptimizationLevel(int graph_optimization_level);
SessionOptions& SetGraphOptimizationLevel(GraphOptimizationLevel graph_optimization_level);

SessionOptions& EnableCpuMemArena();
SessionOptions& DisableCpuMemArena();
Expand Down
2 changes: 1 addition & 1 deletion include/onnxruntime/core/session/onnxruntime_cxx_inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ inline SessionOptions& SessionOptions::SetThreadPoolSize(int session_thread_pool
return *this;
}

inline SessionOptions& SessionOptions::SetGraphOptimizationLevel(int graph_optimization_level) {
inline SessionOptions& SessionOptions::SetGraphOptimizationLevel(GraphOptimizationLevel graph_optimization_level) {
ORT_THROW_ON_ERROR(OrtSetSessionGraphOptimizationLevel(p_, graph_optimization_level));
return *this;
}
Expand Down
22 changes: 17 additions & 5 deletions onnxruntime/core/session/abi_session_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,26 @@ ORT_API_STATUS_IMPL(OrtSetSessionLogVerbosityLevel, _In_ OrtSessionOptions* opti
}

// Set Graph optimization level.
// Available options are : 0, 1, 2.
ORT_API_STATUS_IMPL(OrtSetSessionGraphOptimizationLevel, _In_ OrtSessionOptions* options, int graph_optimization_level) {
ORT_API_STATUS_IMPL(OrtSetSessionGraphOptimizationLevel, _In_ OrtSessionOptions* options,
GraphOptimizationLevel graph_optimization_level) {
if (graph_optimization_level < 0) {
return OrtCreateStatus(ORT_INVALID_ARGUMENT, "graph_optimization_level is not valid");
}
if (graph_optimization_level >= static_cast<int>(onnxruntime::TransformerLevel::MaxTransformerLevel))
return OrtCreateStatus(ORT_INVALID_ARGUMENT, "graph_optimization_level is not valid");
options->value.graph_optimization_level = static_cast<onnxruntime::TransformerLevel>(graph_optimization_level);

switch (graph_optimization_level) {
case ORT_DISABLE_ALL:
options->value.graph_optimization_level = onnxruntime::TransformerLevel::Default;
break;
case ORT_ENABLE_BASIC:
options->value.graph_optimization_level = onnxruntime::TransformerLevel::Level1;
break;
case ORT_ENABLE_ALL:
options->value.graph_optimization_level = onnxruntime::TransformerLevel::Level2;
break;
default:
return OrtCreateStatus(ORT_INVALID_ARGUMENT, "graph_optimization_level is not valid");
pranavsharma marked this conversation as resolved.
Show resolved Hide resolved
}

return nullptr;
}

Expand Down
109 changes: 53 additions & 56 deletions onnxruntime/python/onnxruntime_pybind_state.cc
Original file line number Diff line number Diff line change
Expand Up @@ -448,57 +448,55 @@ including arg name, arg type (contains both type and shape).)pbdoc")
return *(na.Type());
},
"node type")
.def(
"__str__", [](const onnxruntime::NodeArg& na) -> std::string {
std::ostringstream res;
res << "NodeArg(name='" << na.Name() << "', type='" << *(na.Type()) << "', shape=";
auto shape = na.Shape();
std::vector<py::object> arr;
if (shape == nullptr || shape->dim_size() == 0) {
res << "[]";
.def("__str__", [](const onnxruntime::NodeArg& na) -> std::string {
std::ostringstream res;
res << "NodeArg(name='" << na.Name() << "', type='" << *(na.Type()) << "', shape=";
auto shape = na.Shape();
std::vector<py::object> arr;
if (shape == nullptr || shape->dim_size() == 0) {
res << "[]";
} else {
res << "[";
for (int i = 0; i < shape->dim_size(); ++i) {
if (shape->dim(i).has_dim_value()) {
res << shape->dim(i).dim_value();
} else if (shape->dim(i).has_dim_param()) {
res << "'" << shape->dim(i).dim_param() << "'";
} else {
res << "[";
for (int i = 0; i < shape->dim_size(); ++i) {
if (shape->dim(i).has_dim_value()) {
res << shape->dim(i).dim_value();
} else if (shape->dim(i).has_dim_param()) {
res << "'" << shape->dim(i).dim_param() << "'";
} else {
res << "None";
}

if (i < shape->dim_size() - 1) {
res << ", ";
}
}
res << "]";
res << "None";
}
res << ")";

return std::string(res.str());
},
"converts the node into a readable string")
.def_property_readonly(
"shape", [](const onnxruntime::NodeArg& na) -> std::vector<py::object> {
auto shape = na.Shape();
std::vector<py::object> arr;
if (shape == nullptr || shape->dim_size() == 0) {
return arr;
if (i < shape->dim_size() - 1) {
res << ", ";
}
}
res << "]";
}
res << ")";

arr.resize(shape->dim_size());
for (int i = 0; i < shape->dim_size(); ++i) {
if (shape->dim(i).has_dim_value()) {
arr[i] = py::cast(shape->dim(i).dim_value());
} else if (shape->dim(i).has_dim_param()) {
arr[i] = py::cast(shape->dim(i).dim_param());
} else {
arr[i] = py::none();
}
}
return arr;
},
"node shape (assuming the node holds a tensor)");
return std::string(res.str());
},
"converts the node into a readable string")
.def_property_readonly("shape", [](const onnxruntime::NodeArg& na) -> std::vector<py::object> {
auto shape = na.Shape();
std::vector<py::object> arr;
if (shape == nullptr || shape->dim_size() == 0) {
return arr;
}

arr.resize(shape->dim_size());
for (int i = 0; i < shape->dim_size(); ++i) {
if (shape->dim(i).has_dim_value()) {
arr[i] = py::cast(shape->dim(i).dim_value());
} else if (shape->dim(i).has_dim_param()) {
arr[i] = py::cast(shape->dim(i).dim_param());
} else {
arr[i] = py::none();
}
}
return arr;
},
"node shape (assuming the node holds a tensor)");

py::class_<SessionObjectInitializer>(m, "SessionObjectInitializer");
py::class_<InferenceSession>(m, "InferenceSession", R"pbdoc(This is the main class used to run a model.)pbdoc")
Expand All @@ -513,16 +511,15 @@ including arg name, arg type (contains both type and shape).)pbdoc")
InitializeSession(sess);
},
R"pbdoc(Load a model saved in ONNX format.)pbdoc")
.def(
"read_bytes", [](InferenceSession* sess, const py::bytes& serializedModel) {
std::istringstream buffer(serializedModel);
auto status = sess->Load(buffer);
if (!status.IsOK()) {
throw std::runtime_error(status.ToString().c_str());
}
InitializeSession(sess);
},
R"pbdoc(Load a model serialized in ONNX format.)pbdoc")
.def("read_bytes", [](InferenceSession* sess, const py::bytes& serializedModel) {
std::istringstream buffer(serializedModel);
auto status = sess->Load(buffer);
if (!status.IsOK()) {
throw std::runtime_error(status.ToString().c_str());
}
InitializeSession(sess);
},
R"pbdoc(Load a model serialized in ONNX format.)pbdoc")
pranavsharma marked this conversation as resolved.
Show resolved Hide resolved
.def("run", [](InferenceSession* sess, std::vector<std::string> output_names, std::map<std::string, py::object> pyfeeds, RunOptions* run_options = nullptr) -> std::vector<py::object> {
NameMLValMap feeds;
for (auto _ : pyfeeds) {
Expand Down
Loading