Skip to content
Permalink
Browse files

Replace ErrorCode with GlowErrs (#2509)

* Replace ErrorCode with GlowErrs

* don't add more std::promise<llvm::Error>s
  • Loading branch information...
jackm321 committed Mar 12, 2019
1 parent 0e00790 commit c2b3866b3f61f9b1706b60604a217ddbfff3fce5
@@ -115,8 +115,9 @@ void dispatchClassify(unsigned int id, DeviceManager *device, std::string path,
std::promise<void> &finished) {
device->runFunction("resnet50", std::move(context),
[id, path, output, &returned,
&finished](RunIdentifierTy, ResultCode r,
&finished](RunIdentifierTy, llvm::Error err,
std::unique_ptr<ExecutionContext> context) {
EXIT_ON_ERR(std::move(err));
size_t maxIdx = context->getPlaceholderBindings()
->get(output)
->getHandle<>()
@@ -20,6 +20,7 @@
#include "glow/Importer/Caffe2ModelLoader.h"
#include "glow/Runtime/HostManager/HostManager.h"
#include "glow/Runtime/RuntimeTypes.h"
#include "glow/Support/Error.h"

#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
@@ -76,21 +77,17 @@ void dispatchClassify(unsigned int id, HostManager *hostManager,
auto runid = hostManager->runNetwork(
"resnet50" + std::to_string(id), std::move(context),
[id, path, &returned,
&finished](RunIdentifierTy, ResultCode r,
&finished](RunIdentifierTy, llvm::Error err,
std::unique_ptr<ExecutionContext> context) {
if (r == ResultCode::Canceled) {
llvm::outs() << "(" << id << ") "
<< "Too Many Active Requests.\n";
} else {
auto *bindings = context->getPlaceholderBindings();
size_t maxIdx =
bindings
->get(bindings->getPlaceholderByName("save_gpu_0_softmax"))
->getHandle()
.minMaxArg()
.second;
llvm::outs() << "(" << id << ") " << path << ": " << maxIdx << "\n";
}
EXIT_ON_ERR(std::move(err));
auto *bindings = context->getPlaceholderBindings();
size_t maxIdx =
bindings->get(bindings->getPlaceholderByName("save_gpu_0_softmax"))
->getHandle()
.minMaxArg()
.second;
llvm::outs() << "(" << id << ") " << path << ": " << maxIdx << "\n";

if (++returned == maxImages) {
finished.set_value();
}
@@ -128,11 +125,7 @@ int main(int argc, char **argv) {
input = loadResnet50Model(inputType, module.get(), i);
inputs.push_back(input);
llvm::outs() << "Adding to HostManager\n";
auto result = hostManager->addNetwork(module.get());
if (result != ResultCode::Ready) {
llvm::outs() << "failed to add\n";
return -1;
}
EXIT_ON_ERR(hostManager->addNetwork(module.get()));
modules.push_back(std::move(module));
}

@@ -151,8 +151,9 @@ int main(int argc, char **argv) {

devices[i]->runFunction(
"resnet50", std::move(context),
[&promises, i](RunIdentifierTy, ResultCode r,
[&promises, i](RunIdentifierTy, llvm::Error err,
std::unique_ptr<ExecutionContext> context) {
EXIT_ON_ERR(std::move(err));
promises[i].set_value(std::move(context));
});
}
@@ -89,7 +89,9 @@ class DeviceManager {
runtime::ResultCBTy resultCB) = 0;

/// Stops execution and shuts down the Device.
virtual ResultCode stop(bool block = true) { return ResultCode::Executed; };
virtual llvm::Error stop(bool block = true) {
return llvm::Error::success();
};

/// \returns the type of Backend that powers this Device.
BackendKind getBackendKind() { return backend_; }
@@ -52,7 +52,8 @@ class DummyDeviceManager : public DeviceManager {
if (functions_.count(func.first) != 0) {
callback(
module,
MAKE_ERR(llvm::formatv("Function {} not found", func.first).str()));
MAKE_ERR(GlowErr::ErrorCode::RUNTIME_NET_NOT_FOUND,
llvm::formatv("Function {} not found", func.first).str()));
return;
}
}
@@ -86,7 +87,11 @@ class DummyDeviceManager : public DeviceManager {
ResultCBTy callback) override {
auto funcIt = functions_.find(functionName);
if (funcIt == functions_.end()) {
callback(0, ResultCode::Failed, std::move(context));
callback(
0,
MAKE_ERR(GlowErr::ErrorCode::RUNTIME_NET_NOT_FOUND,
llvm::formatv("Function {} not found", functionName).str()),
std::move(context));
return 0;
}

@@ -100,7 +105,7 @@ class DummyDeviceManager : public DeviceManager {
func->afterRun(bindings);

// Fire the resultCB.
callback(0, ResultCode::Executed, std::move(context));
callback(0, llvm::Error::success(), std::move(context));

return 0;
}
@@ -38,7 +38,7 @@ class QueueBackedDeviceManager : public DeviceManager {
: DeviceManager(backend, std::move(config)), workThread_(1) {}

virtual ~QueueBackedDeviceManager() {
stop(true); // will join workThread_
llvm::toString(stop(true)); // will join workThread_
}

/// Initialize the device.
@@ -82,9 +82,9 @@ class QueueBackedDeviceManager : public DeviceManager {
}

/// Stops execution and shuts down the Device.
ResultCode stop(bool block = true) override {
llvm::Error stop(bool block = true) override {
workThread_.stop(block);
return ResultCode::Executed;
return llvm::Error::success();
}

protected:
@@ -85,8 +85,8 @@ class HostManager final {
/// Adds the network to the host and does the necessary setup work. This
/// includes partitioning, provisioning, compiling and initializing
/// backends. Additionally DAGs are created for each function and stored in
/// networks_. Returns a result code to indicate success.
ResultCode addNetwork(Module *M);
/// networks_. Returns an llvm::Error containing the results of the operation.
llvm::Error addNetwork(Module *M);

/// Given \p networkName removes that network from the host. This also
/// removes the network from any backends setup to execute it.
@@ -96,7 +96,7 @@ class HostManager final {
bool networkAdded(llvm::StringRef networkName);

/// Removes all networks from the host, and stops execution on all devices.
void clearHost();
llvm::Error clearHost();

/// Runs the network specified by \p networkName using
/// the provided \p context, returns a runIdentifier which refers to the
@@ -19,6 +19,7 @@
#include "glow/Backends/Backend.h"
#include "glow/Backends/BackendUtils.h"
#include "glow/Graph/Graph.h"
#include "glow/Support/Error.h"

#include <map>
#include <string>
@@ -38,15 +39,10 @@ using RunIdentifierTy = size_t;
/// Map of DeviceIDTy -> DeviceManager.
using DeviceManagerMapTy = std::map<DeviceIDTy, std::unique_ptr<DeviceManager>>;

/// Enum to communicate results when communicating with device at initialization
/// and runtime.
enum class ResultCode { Ready, Executed, Failed, Canceled };

/// Callback type used by HostManager and DeviceManager, used to pass results of
/// an inference request back to the caller.
using ResultCBTy =
std::function<void(runtime::RunIdentifierTy, runtime::ResultCode,
std::unique_ptr<ExecutionContext>)>;
using ResultCBTy = std::function<void(runtime::RunIdentifierTy, llvm::Error,
std::unique_ptr<ExecutionContext>)>;

/// Data structure that contains device constraint information for each device.
/// Used to communicate memory constraints and later costs to the Partitioner.
@@ -16,6 +16,7 @@
#ifndef GLOW_SUPPORT_ERROR_H
#define GLOW_SUPPORT_ERROR_H

#include <mutex>
#include <type_traits>

#include "llvm/Support/Error.h"
@@ -67,9 +68,15 @@ class GlowErr final : public llvm::ErrorInfo<GlowErr> {
// Model loader encountered an invalid protobuf.
MODEL_LOADER_INVALID_PROTOBUF,
// Runtime error, out of device memory.
RUNTIME_ERROR,
// Runtime error, out of device memory.
RUNTIME_OUT_OF_DEVICE_MEMORY,
// Runtime error, could not find the specified model network.
RUNTIME_NET_NOT_FOUND,
// Runtime error, runtime refusing to service request.
RUNTIME_REQUEST_REFUSED,
// Runtime error, device wasn't found.
RUNTIME_DEVICE_NOT_FOUND,
};

/// GlowErr is not convertable to std::error_code. This is included for
@@ -125,10 +132,16 @@ class GlowErr final : public llvm::ErrorInfo<GlowErr> {
return "MODEL_LOADER_UNSUPPORTED_ONNX_VERSION";
case ErrorCode::MODEL_LOADER_INVALID_PROTOBUF:
return "MODEL_LOADER_INVALID_PROTOBUF";
case ErrorCode::RUNTIME_ERROR:
return "RUNTIME_ERROR";
case ErrorCode::RUNTIME_OUT_OF_DEVICE_MEMORY:
return "RUNTIME_OUT_OF_DEVICE_MEMORY";
case ErrorCode::RUNTIME_NET_NOT_FOUND:
return "RUNTIME_NET_NOT_FOUND";
case ErrorCode::RUNTIME_REQUEST_REFUSED:
return "RUNTIME_REQUEST_REFUSED";
case ErrorCode::RUNTIME_DEVICE_NOT_FOUND:
return "RUNTIME_DEVICE_NOT_FOUND";
};

llvm_unreachable("unsupported ErrorCode");
@@ -154,10 +167,10 @@ class GlowErr final : public llvm::ErrorInfo<GlowErr> {
/// potential errors up the stack.
#define TEMP_EXIT_ON_ERR(...) (EXIT_ON_ERR(__VA_ARGS__))

/// Make a new llvm::StringError.
/// Make a new GlowErr.
#define MAKE_ERR(...) llvm::make_error<GlowErr>(__FILE__, __LINE__, __VA_ARGS__)

/// Makes a new llvm::StringError and returns it.
/// Makes a new GlowErr and returns it.
#define RETURN_ERR(...) \
do { \
return MAKE_ERR(__VA_ARGS__); \
@@ -188,7 +201,7 @@ class GlowErr final : public llvm::ErrorInfo<GlowErr> {
} \
} while (0)

/// Takes a predicate \p and if it is false then creates a new llvm::StringError
/// Takes a predicate \p and if it is false then creates a new GlowErr
/// and returns it.
#define RETURN_ERR_IF_NOT(p, ...) \
do { \
@@ -200,7 +213,7 @@ class GlowErr final : public llvm::ErrorInfo<GlowErr> {
/// Marks the Error \p err as as checked. \returns true if it contains an
/// error value and prints the message in the error value, returns false
/// otherwise.
inline bool errorToBool(llvm::Error err) {
inline bool errToBool(llvm::Error err) {
if (static_cast<bool>(err)) {
llvm::errs() << "Converting error to boolean: "
<< llvm::toString(std::move(err)) << "\n";
@@ -209,6 +222,29 @@ inline bool errorToBool(llvm::Error err) {
return false;
}

/// This class holds an llvm::Error provided via the add method. If an Error is
/// added when the class already holds an Error, it will discard the new Error
/// in favor of the original one. All methods in OneErrOnly are thread-safe.
class OneErrOnly {
private:
llvm::Error err_ = llvm::Error::success();
std::mutex m_;

public:
/// Add a new llvm::Error \p err to be stored. If an existing Error has
/// already been added then the contents of the new error will be logged and
/// the new err will be discarded. \returns true if \p err was stored and
/// \returns false otherwise. If \p err is an empty Error then does nothing
/// and \returns false;
bool set(llvm::Error err);

/// \returns the stored llvm:Error clearing out the storage of the class.
llvm::Error get();

/// \returns true if contains an Error and false otherwise.
bool containsErr();
};

} // end namespace glow

#endif // GLOW_SUPPORT_ERROR_H
@@ -114,9 +114,10 @@ void CPUDeviceManager::runFunctionImpl(
std::unique_ptr<ExecutionContext> context, ResultCBTy resultCB) {
auto funcIt = functions_.find(function);
if (funcIt == functions_.end()) {
llvm::errs() << "Failed to run function: name " << function
<< " not found.\n";
resultCB(id, ResultCode::Failed, std::move(context));
resultCB(id,
MAKE_ERR(GlowErr::ErrorCode::RUNTIME_NET_NOT_FOUND,
llvm::formatv("Function {} not found", function).str()),
std::move(context));
return;
}

@@ -126,5 +127,5 @@ void CPUDeviceManager::runFunctionImpl(
func->execute(context.get());

// Fire the resultCB.
resultCB(id, ResultCode::Executed, std::move(context));
resultCB(id, llvm::Error::success(), std::move(context));
}
@@ -110,9 +110,10 @@ void InterpreterDeviceManager::runFunctionImpl(
std::unique_ptr<ExecutionContext> context, ResultCBTy resultCB) {
auto funcIt = functions_.find(function);
if (funcIt == functions_.end()) {
llvm::errs() << "Failed to run function: name " << function
<< " not found.\n";
resultCB(id, ResultCode::Failed, std::move(context));
resultCB(id,
MAKE_ERR(GlowErr::ErrorCode::RUNTIME_NET_NOT_FOUND,
llvm::formatv("Function {} not found", function).str()),
std::move(context));
return;
}

@@ -122,7 +123,7 @@ void InterpreterDeviceManager::runFunctionImpl(
func->execute(context.get());

// Fire the resultCB.
resultCB(id, ResultCode::Executed, std::move(context));
resultCB(id, llvm::Error::success(), std::move(context));
}

} // namespace runtime
@@ -241,9 +241,10 @@ void OpenCLDeviceManager::runFunctionImpl(
std::unique_ptr<ExecutionContext> context, ResultCBTy resultCB) {
auto funcIt = functions_.find(function);
if (funcIt == functions_.end()) {
llvm::errs() << "Failed to run function: name " << function
<< " not found.\n";
resultCB(id, ResultCode::Failed, std::move(context));
resultCB(id,
MAKE_ERR(GlowErr::ErrorCode::RUNTIME_NET_NOT_FOUND,
llvm::formatv("Function {} not found", function).str()),
std::move(context));
return;
}

@@ -259,5 +260,5 @@ void OpenCLDeviceManager::runFunctionImpl(
func->afterRun(bindings);

// Fire the resultCB.
resultCB(id, ResultCode::Executed, std::move(context));
resultCB(id, llvm::Error::success(), std::move(context));
}
@@ -48,7 +48,7 @@ void ExecutionEngine::setBackend(Backend *backend, bool ownsBackend) {

if (differentKinds) {
if (device_) {
device_->stop();
EXIT_ON_ERR(device_->stop());
device_.reset();
}

@@ -118,20 +118,21 @@ void ExecutionEngine::runInternal(ExecutionContext &context,
context.getPlaceholderBindings()->allocate(M_.getPlaceholders());

std::unique_ptr<ExecutionContext> contextPtr(&context);
std::promise<runtime::ResultCode> runPromise;
std::promise<void> runPromise;
auto fut = runPromise.get_future();
llvm::Error runErr = llvm::Error::success();
device_->runFunction(
name, std::move(contextPtr),
[&runPromise](runtime::RunIdentifierTy, runtime::ResultCode code,
std::unique_ptr<ExecutionContext> contextPtr) {
[&runPromise, &runErr](runtime::RunIdentifierTy, llvm::Error err,
std::unique_ptr<ExecutionContext> contextPtr) {
// Don't delete context.
contextPtr.release();
runPromise.set_value(code);
runErr = std::move(err);
runPromise.set_value();
});

fut.wait();
assert(fut.get() == runtime::ResultCode::Executed &&
"Function failed to execute");
EXIT_ON_ERR(std::move(runErr));
}

void ExecutionEngine::run(ExecutionContext &context) {
Oops, something went wrong.

0 comments on commit c2b3866

Please sign in to comment.
You can’t perform that action at this time.