diff options
author | Manjunath Kudlur <keveman@gmail.com> | 2015-11-06 16:27:58 -0800 |
---|---|---|
committer | Manjunath Kudlur <keveman@gmail.com> | 2015-11-06 16:27:58 -0800 |
commit | f41959ccb2d9d4c722fe8fc3351401d53bcf4900 (patch) | |
tree | ef0ca22cb2a5ac4bdec9d080d8e0788a53ed496d /tensorflow/stream_executor/lib |
TensorFlow: Initial commit of TensorFlow library.
TensorFlow is an open source software library for numerical computation
using data flow graphs.
Base CL: 107276108
Diffstat (limited to 'tensorflow/stream_executor/lib')
29 files changed, 1132 insertions, 0 deletions
diff --git a/tensorflow/stream_executor/lib/array_slice.h b/tensorflow/stream_executor/lib/array_slice.h new file mode 100644 index 0000000000..271b1c15a0 --- /dev/null +++ b/tensorflow/stream_executor/lib/array_slice.h @@ -0,0 +1,17 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_ARRAY_SLICE_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_ARRAY_SLICE_H_ + +#include "tensorflow/core/lib/gtl/array_slice.h" + +namespace perftools { +namespace gputools { +namespace port { + +using tensorflow::gtl::ArraySlice; +using tensorflow::gtl::MutableArraySlice; + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_ARRAY_SLICE_H_ diff --git a/tensorflow/stream_executor/lib/casts.h b/tensorflow/stream_executor/lib/casts.h new file mode 100644 index 0000000000..61ff2ab00e --- /dev/null +++ b/tensorflow/stream_executor/lib/casts.h @@ -0,0 +1,85 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_CASTS_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_CASTS_H_ + +#include <stdlib.h> + +namespace perftools { +namespace gputools { +namespace port { + +// port::bit_cast<Dest,Source> is a template function that implements the +// equivalent of "*reinterpret_cast<Dest*>(&source)". We need this in +// very low-level functions like the protobuf library and fast math +// support. +// +// float f = 3.14159265358979; +// int i = port::bit_cast<int32>(f); +// // i = 0x40490fdb +// +// The classical address-casting method is: +// +// // WRONG +// float f = 3.14159265358979; // WRONG +// int i = * reinterpret_cast<int*>(&f); // WRONG +// +// The address-casting method actually produces undefined behavior +// according to ISO C++ specification section 3.10 -15 -. Roughly, this +// section says: if an object in memory has one type, and a program +// accesses it with a different type, then the result is undefined +// behavior for most values of "different type". +// +// This is true for any cast syntax, either *(int*)&f or +// *reinterpret_cast<int*>(&f). And it is particularly true for +// conversions between integral lvalues and floating-point lvalues. +// +// The purpose of 3.10 -15- is to allow optimizing compilers to assume +// that expressions with different types refer to different memory. gcc +// 4.0.1 has an optimizer that takes advantage of this. So a +// non-conforming program quietly produces wildly incorrect output. +// +// The problem is not the use of reinterpret_cast. The problem is type +// punning: holding an object in memory of one type and reading its bits +// back using a different type. +// +// The C++ standard is more subtle and complex than this, but that +// is the basic idea. +// +// Anyways ... +// +// port::bit_cast<> calls memcpy() which is blessed by the standard, +// especially by the example in section 3.9 . Also, of course, +// port::bit_cast<> wraps up the nasty logic in one place. +// +// Fortunately memcpy() is very fast. In optimized mode, with a +// constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline +// code with the minimal amount of data movement. On a 32-bit system, +// memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8) +// compiles to two loads and two stores. +// +// I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1. +// +// WARNING: if Dest or Source is a non-POD type, the result of the memcpy +// is likely to surprise you. +// +// Props to Bill Gibbons for the compile time assertion technique and +// Art Komninos and Igor Tandetnik for the msvc experiments. +// +// -- mec 2005-10-17 + +template <class Dest, class Source> +inline Dest bit_cast(const Source& source) { + // Compile time assertion: sizeof(Dest) == sizeof(Source) + // A compile error here means your Dest and Source have different sizes. + static_assert(sizeof(Dest) == sizeof(Source), + "src and dst types must have equal sizes"); + + Dest dest; + memcpy(&dest, &source, sizeof(dest)); + return dest; +} + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_CASTS_H_ diff --git a/tensorflow/stream_executor/lib/demangle.cc b/tensorflow/stream_executor/lib/demangle.cc new file mode 100644 index 0000000000..6b837b803a --- /dev/null +++ b/tensorflow/stream_executor/lib/demangle.cc @@ -0,0 +1,38 @@ +#include "tensorflow/stream_executor/lib/demangle.h" + +#if (__GNUC__ >= 4 || (__GNUC__ >= 3 && __GNUC_MINOR__ >= 4)) && \ + !defined(__mips__) +# define HAS_CXA_DEMANGLE 1 +#else +# define HAS_CXA_DEMANGLE 0 +#endif + +#include <stdlib.h> +#if HAS_CXA_DEMANGLE +#include <cxxabi.h> +#endif + +namespace perftools { +namespace gputools { +namespace port { + +// The API reference of abi::__cxa_demangle() can be found in +// libstdc++'s manual. +// https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html +string Demangle(const char *mangled) { + string demangled; + int status = 0; + char *result = NULL; +#if HAS_CXA_DEMANGLE + result = abi::__cxa_demangle(mangled, NULL, NULL, &status); +#endif + if (status == 0 && result != NULL) { // Demangling succeeeded. + demangled.append(result); + free(result); + } + return demangled; +} + +} // namespace port +} // namespace gputools +} // namespace perftools diff --git a/tensorflow/stream_executor/lib/demangle.h b/tensorflow/stream_executor/lib/demangle.h new file mode 100644 index 0000000000..0420f7101f --- /dev/null +++ b/tensorflow/stream_executor/lib/demangle.h @@ -0,0 +1,16 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_DEMANGLE_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_DEMANGLE_H_ + +#include "tensorflow/stream_executor/platform/port.h" + +namespace perftools { +namespace gputools { +namespace port { + +string Demangle(const char* mangled); + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_DEMANGLE_H_ diff --git a/tensorflow/stream_executor/lib/env.h b/tensorflow/stream_executor/lib/env.h new file mode 100644 index 0000000000..74b50ad42d --- /dev/null +++ b/tensorflow/stream_executor/lib/env.h @@ -0,0 +1,29 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_ENV_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_ENV_H_ + +#include "tensorflow/core/public/env.h" +#include "tensorflow/stream_executor/lib/stringpiece.h" +#include "tensorflow/stream_executor/platform/port.h" + +namespace perftools { +namespace gputools { +namespace port { + +using tensorflow::Env; +using tensorflow::ReadFileToString; +using tensorflow::Thread; +using tensorflow::WriteStringToFile; + +inline bool FileExists(const string& filename) { + return Env::Default()->FileExists(filename); +} + +inline bool FileExists(const port::StringPiece& filename) { + return Env::Default()->FileExists(filename.ToString()); +} + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_ENV_H_ diff --git a/tensorflow/stream_executor/lib/error.h b/tensorflow/stream_executor/lib/error.h new file mode 100644 index 0000000000..376ddd3d07 --- /dev/null +++ b/tensorflow/stream_executor/lib/error.h @@ -0,0 +1,16 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_ERROR_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_ERROR_H_ + +#include "tensorflow/core/lib/core/error_codes.pb.h" + +namespace perftools { +namespace gputools { +namespace port { + +namespace error = tensorflow::error; + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_ERROR_H_ diff --git a/tensorflow/stream_executor/lib/human_readable.h b/tensorflow/stream_executor/lib/human_readable.h new file mode 100644 index 0000000000..78df4a4a70 --- /dev/null +++ b/tensorflow/stream_executor/lib/human_readable.h @@ -0,0 +1,58 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_HUMAN_READABLE_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_HUMAN_READABLE_H_ + +#include <assert.h> +#include <limits> + +#include "tensorflow/stream_executor/lib/stringprintf.h" +#include "tensorflow/stream_executor/platform/port.h" + +namespace perftools { +namespace gputools { +namespace port { + +class HumanReadableNumBytes { + public: + static string ToString(int64 num_bytes) { + if (num_bytes == std::numeric_limits<int64>::min()) { + // Special case for number with not representable nagation. + return "-8E"; + } + + const char* neg_str = GetNegStr(&num_bytes); + + // Special case for bytes. + if (num_bytes < 1024LL) { + // No fractions for bytes. + return port::Printf("%s%lldB", neg_str, num_bytes); + } + + static const char units[] = "KMGTPE"; // int64 only goes up to E. + const char* unit = units; + while (num_bytes >= (1024LL) * (1024LL)) { + num_bytes /= (1024LL); + ++unit; + assert(unit < units + sizeof(units)); + } + + return port::Printf(((*unit == 'K') ? "%s%.1f%c" : "%s%.2f%c"), neg_str, + num_bytes / 1024.0, *unit); + } + + private: + template <typename T> + static const char* GetNegStr(T* value) { + if (*value < 0) { + *value = -(*value); + return "-"; + } else { + return ""; + } + } +}; + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_HUMAN_READABLE_H_ diff --git a/tensorflow/stream_executor/lib/initialize.h b/tensorflow/stream_executor/lib/initialize.h new file mode 100644 index 0000000000..d1832d6b26 --- /dev/null +++ b/tensorflow/stream_executor/lib/initialize.h @@ -0,0 +1,35 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_INITIALIZE_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_INITIALIZE_H_ + +#include "tensorflow/stream_executor/platform/port.h" + +#if defined(PLATFORM_GOOGLE) +#else + +#undef REGISTER_MODULE_INITIALIZER + +namespace perftools { +namespace gputools { +namespace port { + +class Initializer { + public: + typedef void (*InitializerFunc)(); + explicit Initializer(InitializerFunc func) { func(); } +}; + +} // namespace port +} // namespace gputools +} // namespace perftools + +#define REGISTER_INITIALIZER(type, name, body) \ + static void google_init_##type##_##name() { body; } \ + perftools::gputools::port::Initializer google_initializer_##type##_##name( \ + google_init_##type##_##name) + +#define REGISTER_MODULE_INITIALIZER(name, body) \ + REGISTER_INITIALIZER(module, name, body) + +#endif // !defined(PLATFORM_GOOGLE) + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_INITIALIZE_H_ diff --git a/tensorflow/stream_executor/lib/inlined_vector.h b/tensorflow/stream_executor/lib/inlined_vector.h new file mode 100644 index 0000000000..e1f7a29904 --- /dev/null +++ b/tensorflow/stream_executor/lib/inlined_vector.h @@ -0,0 +1,16 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_INLINED_VECTOR_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_INLINED_VECTOR_H_ + +#include "tensorflow/core/lib/gtl/inlined_vector.h" + +namespace perftools { +namespace gputools { +namespace port { + +using tensorflow::gtl::InlinedVector; + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_INLINED_VECTOR_H_ diff --git a/tensorflow/stream_executor/lib/mathutil.h b/tensorflow/stream_executor/lib/mathutil.h new file mode 100644 index 0000000000..dd3d37a19c --- /dev/null +++ b/tensorflow/stream_executor/lib/mathutil.h @@ -0,0 +1,88 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_MATHUTIL_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_MATHUTIL_H_ + +#include <algorithm> +#include <cmath> +#include <limits> +#include <type_traits> +#include <vector> + +#include "tensorflow/stream_executor/platform/logging.h" +#include "tensorflow/stream_executor/platform/port.h" + +namespace perftools { +namespace gputools { +namespace port { + +class MathUtil { + public: + template <typename IntegralType> + static IntegralType CeilOfRatio(IntegralType numerator, + IntegralType denominator) { + return CeilOrFloorOfRatio<IntegralType, true>(numerator, denominator); + } + template <typename IntegralType> + static IntegralType FloorOfRatio(IntegralType numerator, + IntegralType denominator) { + return CeilOrFloorOfRatio<IntegralType, false>(numerator, denominator); + } + template <typename IntegralType, bool ceil> + static IntegralType CeilOrFloorOfRatio(IntegralType numerator, + IntegralType denominator); +}; + +// ---- CeilOrFloorOfRatio ---- +// This is a branching-free, cast-to-double-free implementation. +// +// Casting to double is in general incorrect because of loss of precision +// when casting an int64 into a double. +// +// There's a bunch of 'recipes' to compute a integer ceil (or floor) on the web, +// and most of them are incorrect. +template<typename IntegralType, bool ceil> +IntegralType MathUtil::CeilOrFloorOfRatio(IntegralType numerator, + IntegralType denominator) { + static_assert(std::is_integral<IntegralType>::value, + "CeilOfRatio_is_only_defined_for_integral_types"); + assert(denominator != 0); + // Dividing the smallest signed integer by -1 is not supported: it would + // SIGFPE + assert(!std::is_signed<IntegralType>::value || + numerator != std::numeric_limits<IntegralType>::min() || + denominator != -1); + + const IntegralType rounded_toward_zero = numerator / denominator; + const IntegralType intermediate_product = rounded_toward_zero * denominator; + + if (ceil) { // Compile-time condition: not an actual branching + // When rounded_toward_zero is negative, then an adjustment is never needed: + // the real ratio is negative, and so rounded toward zero is the ceil. + // When rounded_toward_zero is non-negative, an adjustment is needed if the + // sign of the difference numerator - intermediate_product is the same as + // the sign of the denominator. + // + // Using a bool and then a static_cast to IntegralType is not strictly + // necessary, but it makes the code clear, and anyway the compiler should + // get rid of it. + const bool needs_adjustment = (rounded_toward_zero >= 0) && + ((denominator > 0 && numerator > intermediate_product) || + (denominator < 0 && numerator < intermediate_product)); + const IntegralType adjustment = static_cast<IntegralType>(needs_adjustment); + const IntegralType ceil_of_ratio = rounded_toward_zero + adjustment; + return ceil_of_ratio; + } else { + // Floor case: symmetrical to the previous one + const bool needs_adjustment = (rounded_toward_zero <= 0) && + ((denominator > 0 && numerator < intermediate_product) || + (denominator < 0 && numerator > intermediate_product)); + const IntegralType adjustment = static_cast<IntegralType>(needs_adjustment); + const IntegralType floor_of_ratio = rounded_toward_zero - adjustment; + return floor_of_ratio; + } +} + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_MATHUTIL_H_ diff --git a/tensorflow/stream_executor/lib/notification.h b/tensorflow/stream_executor/lib/notification.h new file mode 100644 index 0000000000..2baa458fc9 --- /dev/null +++ b/tensorflow/stream_executor/lib/notification.h @@ -0,0 +1,16 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_NOTIFICATION_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_NOTIFICATION_H_ + +#include "tensorflow/core/lib/core/notification.h" + +namespace perftools { +namespace gputools { +namespace port { + +using tensorflow::Notification; + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_NOTIFICATION_H_ diff --git a/tensorflow/stream_executor/lib/numbers.cc b/tensorflow/stream_executor/lib/numbers.cc new file mode 100644 index 0000000000..a9981b0ce6 --- /dev/null +++ b/tensorflow/stream_executor/lib/numbers.cc @@ -0,0 +1,27 @@ +#include "tensorflow/stream_executor/lib/numbers.h" + +#include <stdlib.h> + +namespace perftools { +namespace gputools { +namespace port { + +bool safe_strto32(const char* str, int32* value) { + char* endptr; + *value = strtol(str, &endptr, 10); // NOLINT + if (endptr != str) { + while (isspace(*endptr)) ++endptr; + } + return *str != '\0' && *endptr == '\0'; +} + +// Convert strings to floating point values. +// Leading and trailing spaces are allowed. +// Values may be rounded on over- and underflow. +bool safe_strto32(const string& str, int32* value) { + return port::safe_strto32(str.c_str(), value); +} + +} // namespace port +} // namespace gputools +} // namespace perftools diff --git a/tensorflow/stream_executor/lib/numbers.h b/tensorflow/stream_executor/lib/numbers.h new file mode 100644 index 0000000000..17b2893743 --- /dev/null +++ b/tensorflow/stream_executor/lib/numbers.h @@ -0,0 +1,19 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_NUMBERS_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_NUMBERS_H_ + +#include "tensorflow/stream_executor/platform/port.h" + +namespace perftools { +namespace gputools { +namespace port { + +// Convert strings to floating point values. +// Leading and trailing spaces are allowed. +// Values may be rounded on over- and underflow. +bool safe_strto32(const string& str, int32* value); + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_NUMBERS_H_ diff --git a/tensorflow/stream_executor/lib/path.cc b/tensorflow/stream_executor/lib/path.cc new file mode 100644 index 0000000000..a6e76e99b7 --- /dev/null +++ b/tensorflow/stream_executor/lib/path.cc @@ -0,0 +1,50 @@ +#include "tensorflow/stream_executor/lib/path.h" +#include "tensorflow/stream_executor/lib/strcat.h" + +using ::perftools::gputools::port::StringPiece; +using ::perftools::gputools::port::StrAppend; + +namespace perftools { +namespace gputools { +namespace port { +namespace internal { + +static bool IsAbsolutePath(port::StringPiece path) { + return !path.empty() && path[0] == '/'; +} + +// For an array of paths of length count, append them all together, +// ensuring that the proper path separators are inserted between them. +string JoinPathImpl(std::initializer_list<port::StringPiece> paths) { + string result; + + for (port::StringPiece path : paths) { + if (path.empty()) continue; + + if (result.empty()) { + result = path.ToString(); + continue; + } + + if (result[result.size() - 1] == '/') { + if (IsAbsolutePath(path)) { + StrAppend(&result, path.substr(1)); + } else { + StrAppend(&result, path); + } + } else { + if (IsAbsolutePath(path)) { + StrAppend(&result, path); + } else { + StrAppend(&result, "/", path); + } + } + } + + return result; +} + +} // namespace internal +} // namespace port +} // namespace gputools +} // namespace perftools diff --git a/tensorflow/stream_executor/lib/path.h b/tensorflow/stream_executor/lib/path.h new file mode 100644 index 0000000000..1d648e8de1 --- /dev/null +++ b/tensorflow/stream_executor/lib/path.h @@ -0,0 +1,44 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_PATH_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_PATH_H_ + +#include "tensorflow/stream_executor/lib/stringpiece.h" +#include "tensorflow/stream_executor/platform/port.h" + +namespace perftools { +namespace gputools { +namespace port { + +namespace internal { +// TODO(rspringer): Move to cc/implementation file. +// Not part of the public API. +string JoinPathImpl(std::initializer_list<port::StringPiece> paths); +} // namespace internal + +// Join multiple paths together. +// JoinPath unconditionally joins all paths together. For example: +// +// Arguments | JoinPath +// ---------------------------+--------------------- +// '/foo', 'bar' | /foo/bar +// '/foo/', 'bar' | /foo/bar +// '/foo', '/bar' | /foo/bar +// '/foo', '/bar', '/baz' | /foo/bar/baz +// +// All paths will be treated as relative paths, regardless of whether or not +// they start with a leading '/'. That is, all paths will be concatenated +// together, with the appropriate path separator inserted in between. +// Arguments must be convertible to port::StringPiece. +// +// Usage: +// string path = file::JoinPath("/var/log", dirname, filename); +// string path = file::JoinPath(FLAGS_test_srcdir, filename); +template <typename... T> +inline string JoinPath(const T&... args) { + return internal::JoinPathImpl({args...}); +} + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_PATH_H_ diff --git a/tensorflow/stream_executor/lib/process_state.cc b/tensorflow/stream_executor/lib/process_state.cc new file mode 100644 index 0000000000..c20493b263 --- /dev/null +++ b/tensorflow/stream_executor/lib/process_state.cc @@ -0,0 +1,37 @@ +#include "tensorflow/stream_executor/lib/process_state.h" + +#include <unistd.h> + +#include <memory> + +namespace perftools { +namespace gputools { +namespace port { + +string Hostname() { + char hostname[1024]; + gethostname(hostname, sizeof hostname); + hostname[sizeof hostname - 1] = 0; + return hostname; +} + +bool GetCurrentDirectory(string* dir) { + size_t len = 128; + std::unique_ptr<char[]> a(new char[len]); + for (;;) { + char* p = getcwd(a.get(), len); + if (p != NULL) { + *dir = p; + return true; + } else if (errno == ERANGE) { + len += len; + a.reset(new char[len]); + } else { + return false; + } + } +} + +} // namespace port +} // namespace gputools +} // namespace perftools diff --git a/tensorflow/stream_executor/lib/process_state.h b/tensorflow/stream_executor/lib/process_state.h new file mode 100644 index 0000000000..b75879499b --- /dev/null +++ b/tensorflow/stream_executor/lib/process_state.h @@ -0,0 +1,17 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_PROCESS_STATE_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_PROCESS_STATE_H_ + +#include "tensorflow/stream_executor/platform/port.h" + +namespace perftools { +namespace gputools { +namespace port { + +string Hostname(); +bool GetCurrentDirectory(string* dir); + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_PROCESS_STATE_H_ diff --git a/tensorflow/stream_executor/lib/ptr_util.h b/tensorflow/stream_executor/lib/ptr_util.h new file mode 100644 index 0000000000..d10d0bcb8c --- /dev/null +++ b/tensorflow/stream_executor/lib/ptr_util.h @@ -0,0 +1,48 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_PTR_UTIL_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_PTR_UTIL_H_ + +namespace perftools { +namespace gputools { +namespace port { + +// Trait to select overloads and return types for MakeUnique. +template <typename T> +struct MakeUniqueResult { + using scalar = std::unique_ptr<T>; +}; +template <typename T> +struct MakeUniqueResult<T[]> { + using array = std::unique_ptr<T[]>; +}; +template <typename T, size_t N> +struct MakeUniqueResult<T[N]> { + using invalid = void; +}; + +// MakeUnique<T>(...) is an early implementation of C++14 std::make_unique. +// It is designed to be 100% compatible with std::make_unique so that the +// eventual switchover will be a simple renaming operation. +template <typename T, typename... Args> +typename MakeUniqueResult<T>::scalar MakeUnique(Args&&... args) { // NOLINT + return std::unique_ptr<T>( + new T(std::forward<Args>(args)...)); // NOLINT(build/c++11) +} + +// Overload for array of unknown bound. +// The allocation of arrays needs to use the array form of new, +// and cannot take element constructor arguments. +template <typename T> +typename MakeUniqueResult<T>::array MakeUnique(size_t n) { + return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]()); +} + +// Reject arrays of known bound. +template <typename T, typename... Args> +typename MakeUniqueResult<T>::invalid MakeUnique(Args&&... /* args */) = + delete; // NOLINT + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_PTR_UTIL_H_ diff --git a/tensorflow/stream_executor/lib/stacktrace.h b/tensorflow/stream_executor/lib/stacktrace.h new file mode 100644 index 0000000000..e7d478efe3 --- /dev/null +++ b/tensorflow/stream_executor/lib/stacktrace.h @@ -0,0 +1,18 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_STACKTRACE_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_STACKTRACE_H_ + +#include "tensorflow/stream_executor/platform/port.h" + +namespace perftools { +namespace gputools { +namespace port { + +#if !defined(PLATFORM_GOOGLE) +inline string CurrentStackTrace() { return "No stack trace available"; } +#endif + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_STACKTRACE_H_ diff --git a/tensorflow/stream_executor/lib/static_threadlocal.h b/tensorflow/stream_executor/lib/static_threadlocal.h new file mode 100644 index 0000000000..9227b2cf0d --- /dev/null +++ b/tensorflow/stream_executor/lib/static_threadlocal.h @@ -0,0 +1,30 @@ +// Copyright 2006 Google Inc. +// All rights reserved. +// Author: Yaz Saito (saito@google.com) +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_STATIC_THREADLOCAL_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_STATIC_THREADLOCAL_H_ + +// For POD types in TLS mode, s_obj_VAR is the thread-local variable. +#define SE_STATIC_THREAD_LOCAL_POD(_Type_, _var_) \ + static thread_local _Type_ s_obj_##_var_; \ + namespace { \ + class ThreadLocal_##_var_ { \ + public: \ + ThreadLocal_##_var_() {} \ + void Init() {} \ + inline _Type_ *pointer() const { \ + return &s_obj_##_var_; \ + } \ + inline _Type_ *safe_pointer() const { \ + return &s_obj_##_var_; \ + } \ + _Type_ &get() const { \ + return s_obj_##_var_; \ + } \ + bool is_native_tls() const { return true; } \ + private: \ + SE_DISALLOW_COPY_AND_ASSIGN(ThreadLocal_##_var_); \ + } _var_; \ + } + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_STATIC_THREADLOCAL_H_ diff --git a/tensorflow/stream_executor/lib/status.h b/tensorflow/stream_executor/lib/status.h new file mode 100644 index 0000000000..b3ad13b0ae --- /dev/null +++ b/tensorflow/stream_executor/lib/status.h @@ -0,0 +1,23 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_STATUS_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_STATUS_H_ + +#include "tensorflow/core/public/status.h" +#include "tensorflow/stream_executor/lib/error.h" +#include "tensorflow/stream_executor/platform/logging.h" + +namespace perftools { +namespace gputools { +namespace port { + +using tensorflow::Status; + +#define SE_CHECK_OK(val) \ + CHECK_EQ(::perftools::gputools::port::Status::OK(), (val)) +#define SE_ASSERT_OK(val) \ + ASSERT_EQ(::perftools::gputools::port::Status::OK(), (val)) + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_STATUS_H_ diff --git a/tensorflow/stream_executor/lib/status_macros.h b/tensorflow/stream_executor/lib/status_macros.h new file mode 100644 index 0000000000..7e1de92a98 --- /dev/null +++ b/tensorflow/stream_executor/lib/status_macros.h @@ -0,0 +1,54 @@ +// Helper macros for dealing with the port::Status datatype. + +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_STATUS_MACROS_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_STATUS_MACROS_H_ + +// Early-returns the status if it is in error; otherwise, proceeds. +// +// The argument expression is guaranteed to be evaluated exactly once. +#define SE_RETURN_IF_ERROR(__status) \ + do { \ + auto status = __status; \ + if (!status.ok()) { \ + return status; \ + } \ + } while (false) + +// Identifier concatenation helper macros. +#define SE_MACRO_CONCAT_INNER(__x, __y) __x##__y +#define SE_MACRO_CONCAT(__x, __y) SE_MACRO_CONCAT_INNER(__x, __y) + +// Implementation of SE_ASSIGN_OR_RETURN that uses a unique temporary identifier +// for avoiding collision in the enclosing scope. +#define SE_ASSIGN_OR_RETURN_IMPL(__lhs, __rhs, __name) \ + auto __name = (__rhs); \ + if (!__name.ok()) { \ + return __name.status(); \ + } \ + __lhs = __name.ConsumeValueOrDie(); + +// Early-returns the status if it is in error; otherwise, assigns the +// right-hand-side expression to the left-hand-side expression. +// +// The right-hand-side expression is guaranteed to be evaluated exactly once. +#define SE_ASSIGN_OR_RETURN(__lhs, __rhs) \ + SE_ASSIGN_OR_RETURN_IMPL(__lhs, __rhs, \ + SE_MACRO_CONCAT(__status_or_value, __COUNTER__)) + +// Logs the status and returns false if it is in error; otherwise, returns true. +// +// The argument expression is guaranteed to be evaluated exactly once. +// +// TODO(leary) remove as many of these as possible with port::Status +// proliferation. +#define SE_RETURN_STATUS_AS_BOOL(__status) \ + do { \ + auto status = __status; \ + if (__status.ok()) { \ + return true; \ + } \ + LOG(ERROR) << status; \ + return false; \ + } while (false) + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_STATUS_MACROS_H_ diff --git a/tensorflow/stream_executor/lib/statusor.h b/tensorflow/stream_executor/lib/statusor.h new file mode 100644 index 0000000000..38ce35e46e --- /dev/null +++ b/tensorflow/stream_executor/lib/statusor.h @@ -0,0 +1,234 @@ +// Copyright 2008 Google Inc. All Rights Reserved. +// Author: acm@google.com (Andrew Morrow) +// Author: zhengxq@google.com (Xiaoqiang Zheng) +// +// StatusOr<T> is the union of a Status object and a T +// object. StatusOr models the concept of an object that is either a +// usable value, or an error Status explaining why such a value is +// not present. To this end, StatusOr<T> does not allow its Status +// value to be Status::OK. Further, StatusOr<T*> does not allow the +// contained pointer to be NULL. +// +// The primary use-case for StatusOr<T> is as the return value of a +// function which may fail. +// +// Example client usage for a StatusOr<T>, where T is not a pointer: +// +// StatusOr<float> result = DoBigCalculationThatCouldFail(); +// if (result.ok()) { +// float answer = result.ValueOrDie(); +// printf("Big calculation yielded: %f", answer); +// } else { +// LOG(ERROR) << result.status(); +// } +// +// Example client usage for a StatusOr<T*>: +// +// StatusOr<Foo*> result = FooFactory::MakeNewFoo(arg); +// if (result.ok()) { +// std::unique_ptr<Foo> foo(result.ValueOrDie()); +// foo->DoSomethingCool(); +// } else { +// LOG(ERROR) << result.status(); +// } +// +// Example client usage for a StatusOr<std::unique_ptr<T>>: +// +// StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg); +// if (result.ok()) { +// std::unique_ptr<Foo> foo = result.ConsumeValueOrDie(); +// foo->DoSomethingCool(); +// } else { +// LOG(ERROR) << result.status(); +// } +// +// Example factory implementation returning StatusOr<T*>: +// +// StatusOr<Foo*> FooFactory::MakeNewFoo(int arg) { +// if (arg <= 0) { +// return Status(port::error::INVALID_ARGUMENT, +// "Arg must be positive"); +// } else { +// return new Foo(arg); +// } +// } +// + +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_STATUSOR_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_STATUSOR_H_ + +#include <new> +#include "tensorflow/stream_executor/platform/port.h" +#include <type_traits> +#include <utility> + +#include "tensorflow/stream_executor/lib/error.h" +#include "tensorflow/stream_executor/lib/status.h" +#include "tensorflow/stream_executor/platform/logging.h" +#include "tensorflow/stream_executor/platform/port.h" + +namespace perftools { +namespace gputools { +namespace port { + +template<typename T> +class StatusOr { + template<typename U> friend class StatusOr; + + public: + // Construct a new StatusOr with Status::UNKNOWN status + StatusOr() : status_(error::UNKNOWN, "") {} + + // Construct a new StatusOr with the given non-ok status. After calling + // this constructor, calls to ValueOrDie() is invalid. + // + // NOTE: Not explicit - we want to use StatusOr<T> as a return + // value, so it is convenient and sensible to be able to do 'return + // Status()' when the return type is StatusOr<T>. + // + // REQUIRES: status != Status::OK. + // In optimized builds, passing Status::OK here will have the effect + // of passing PosixErrorSpace::EINVAL as a fallback. + StatusOr(const Status& status); // NOLINT + + // Construct a new StatusOr with the given value. If T is a plain pointer, + // value must not be NULL. After calling this constructor, calls to + // ValueOrDie() will succeed, and calls to status() will return OK. + // + // NOTE: Not explicit - we want to use StatusOr<T> as a return type + // so it is convenient and sensible to be able to do 'return T()' + // when when the return type is StatusOr<T>. + // + // REQUIRES: if T is a plain pointer, value != NULL. + // In optimized builds, passing a NULL pointer here will have + // the effect of passing PosixErrorSpace::EINVAL as a fallback. + StatusOr(const T& value); // NOLINT + + // Conversion copy constructor, T must be copy constructible from U + template <typename U> + StatusOr(const StatusOr<U>& other) // NOLINT + : status_(other.status_), + value_(other.value_) {} + + // Conversion assignment operator, T must be assignable from U + template <typename U> + StatusOr& operator=(const StatusOr<U>& other) { + status_ = other.status_; + value_ = other.value_; + return *this; + } + + // Rvalue-reference overloads of the other constructors and assignment + // operators, to support move-only types and avoid unnecessary copying. + StatusOr(T&& value); // NOLINT + + // Move conversion operator to avoid unecessary copy. + // T must be assignable from U. + // Not marked with explicit so the implicit conversion can happen. + template <typename U> + StatusOr(StatusOr<U>&& other) // NOLINT + : status_(std::move(other.status_)), + value_(std::move(other.value_)) {} + + // Move assignment opeartor to avoid unnecessary copy. + // T must be assignable from U + template <typename U> + StatusOr& operator=(StatusOr<U>&& other) { + status_ = std::move(other.status_); + value_ = std::move(other.value_); + return *this; + } + + // Returns a reference to our status. If this contains a T, then + // returns Status::OK. + const Status& status() const { return status_; } + + // Returns this->status().ok() + bool ok() const { return status_.ok(); } + + // Returns a reference to our current value, requires that this->ok(). + // If you need to initialize a T object from the stored value, + // ConsumeValueOrDie() may be more efficient. + const T& ValueOrDie() const; + + // Returns our current value, requires this->ok(). Use this if + // you would otherwise want to say std::move(s.ValueOrDie()), for example + // if you need to initialize a T object from the stored value and you don't + // need subsequent access to the stored value. It uses T's move constructor, + // if it has one, so it will work with move-only types, and will often be + // more efficient than ValueOrDie, but may leave the stored value + // in an arbitrary valid state. + T ConsumeValueOrDie(); + + private: + Status status_; + T value_; + + void CheckValueNotNull(const T& value); + + template <typename U> + struct IsNull { + // For non-pointer U, a reference can never be NULL. + static inline bool IsValueNull(const U& t) { return false; } + }; + + template <typename U> + struct IsNull<U*> { + static inline bool IsValueNull(const U* t) { return t == NULL; } + }; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Implementation details for StatusOr<T> + +template <typename T> +StatusOr<T>::StatusOr(const T& value) + : status_(), value_(value) { + CheckValueNotNull(value); +} + +template <typename T> +const T& StatusOr<T>::ValueOrDie() const { + assert(status_.ok()); + return value_; +} + +template <typename T> +T StatusOr<T>::ConsumeValueOrDie() { + assert(status_.ok()); + return std::move(value_); +} + +template <typename T> +StatusOr<T>::StatusOr(const Status& status) + : status_(status) { + assert(!status.ok()); + if (status.ok()) { + status_ = + Status(error::INTERNAL, + "Status::OK is not a valid constructor argument to StatusOr<T>"); + } +} + +template <typename T> +StatusOr<T>::StatusOr(T&& value) + : status_() { + CheckValueNotNull(value); + value_ = std::move(value); +} + +template <typename T> +void StatusOr<T>::CheckValueNotNull(const T& value) { + assert(!IsNull<T>::IsValueNull(value)); + if (IsNull<T>::IsValueNull(value)) { + status_ = + Status(error::INTERNAL, + "NULL is not a valid constructor argument to StatusOr<T*>"); + } +} + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_STATUSOR_H_ diff --git a/tensorflow/stream_executor/lib/str_util.h b/tensorflow/stream_executor/lib/str_util.h new file mode 100644 index 0000000000..021f54dfec --- /dev/null +++ b/tensorflow/stream_executor/lib/str_util.h @@ -0,0 +1,30 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_STR_UTIL_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_STR_UTIL_H_ + +#include "tensorflow/core/lib/strings/str_util.h" +#include "tensorflow/stream_executor/lib/stringpiece.h" + +namespace perftools { +namespace gputools { +namespace port { + +using tensorflow::str_util::Join; +using tensorflow::str_util::Split; + +// Returns a copy of the input string 'str' with the given 'suffix' +// removed. If the suffix doesn't match, returns a copy of the original string. +inline string StripSuffixString(port::StringPiece str, port::StringPiece suffix) { + if (str.ends_with(suffix)) { + str.remove_suffix(suffix.size()); + } + return str.ToString(); +} + +using tensorflow::str_util::Lowercase; +using tensorflow::str_util::Uppercase; + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_STR_UTIL_H_ diff --git a/tensorflow/stream_executor/lib/strcat.h b/tensorflow/stream_executor/lib/strcat.h new file mode 100644 index 0000000000..b3fe4da327 --- /dev/null +++ b/tensorflow/stream_executor/lib/strcat.h @@ -0,0 +1,17 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_STRCAT_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_STRCAT_H_ + +#include "tensorflow/core/lib/strings/strcat.h" + +namespace perftools { +namespace gputools { +namespace port { + +using tensorflow::strings::StrCat; +using tensorflow::strings::StrAppend; + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_STRCAT_H_ diff --git a/tensorflow/stream_executor/lib/stringpiece.h b/tensorflow/stream_executor/lib/stringpiece.h new file mode 100644 index 0000000000..14e6fc99d7 --- /dev/null +++ b/tensorflow/stream_executor/lib/stringpiece.h @@ -0,0 +1,17 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_STRINGPIECE_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_STRINGPIECE_H_ + +#include "tensorflow/core/lib/core/stringpiece.h" +#include "tensorflow/stream_executor/platform/port.h" + +namespace perftools { +namespace gputools { +namespace port { + +using tensorflow::StringPiece; + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_STRINGPIECE_H_ diff --git a/tensorflow/stream_executor/lib/stringprintf.h b/tensorflow/stream_executor/lib/stringprintf.h new file mode 100644 index 0000000000..379e7e9a83 --- /dev/null +++ b/tensorflow/stream_executor/lib/stringprintf.h @@ -0,0 +1,18 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_STRINGPRINTF_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_STRINGPRINTF_H_ + +#include "tensorflow/core/lib/strings/stringprintf.h" + +namespace perftools { +namespace gputools { +namespace port { + +using tensorflow::strings::Printf; +using tensorflow::strings::Appendf; +using tensorflow::strings::Appendv; + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_STRINGPRINTF_H_ diff --git a/tensorflow/stream_executor/lib/thread_options.h b/tensorflow/stream_executor/lib/thread_options.h new file mode 100644 index 0000000000..7d436578d6 --- /dev/null +++ b/tensorflow/stream_executor/lib/thread_options.h @@ -0,0 +1,16 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_THREAD_OPTIONS_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_THREAD_OPTIONS_H_ + +#include "tensorflow/core/public/env.h" + +namespace perftools { +namespace gputools { +namespace port { + +using tensorflow::ThreadOptions; + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_THREAD_OPTIONS_H_ diff --git a/tensorflow/stream_executor/lib/threadpool.h b/tensorflow/stream_executor/lib/threadpool.h new file mode 100644 index 0000000000..3cf297d57b --- /dev/null +++ b/tensorflow/stream_executor/lib/threadpool.h @@ -0,0 +1,19 @@ +#ifndef TENSORFLOW_STREAM_EXECUTOR_LIB_THREADPOOL_H_ +#define TENSORFLOW_STREAM_EXECUTOR_LIB_THREADPOOL_H_ + +#include "tensorflow/core/lib/core/threadpool.h" +#include "tensorflow/stream_executor/lib/env.h" +#include "tensorflow/stream_executor/lib/notification.h" +#include "tensorflow/stream_executor/lib/thread_options.h" + +namespace perftools { +namespace gputools { +namespace port { + +using tensorflow::thread::ThreadPool; + +} // namespace port +} // namespace gputools +} // namespace perftools + +#endif // TENSORFLOW_STREAM_EXECUTOR_LIB_THREADPOOL_H_ |