[
"cuda/*.cc",
],
- exclude = ["cuda/cuda_platform_id.cc"],
+ exclude = [
+ "cuda/*_test.cc",
+ "cuda/cuda_platform_id.cc",
+ ],
),
),
copts = select({
":stream_executor",
"//tensorflow/core:lib",
"//tensorflow/core/kernels:ops_util",
+ "@com_google_absl//absl/strings",
"@local_config_cuda//cuda:cuda_headers",
] + if_cuda_is_configured([
"//tensorflow/core:cuda",
#include <functional>
#include <memory>
+#include "absl/strings/str_cat.h"
#include "third_party/eigen3/Eigen/Core"
+#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/util/env_var.h"
#include "tensorflow/stream_executor/cuda/cuda_activation.h"
#include "tensorflow/stream_executor/cuda/cuda_diagnostics.h"
#include "tensorflow/stream_executor/cuda/cuda_platform_id.h"
#include "tensorflow/stream_executor/cuda/cuda_stream.h"
#include "tensorflow/stream_executor/cuda/cuda_timer.h"
+#include "tensorflow/stream_executor/cuda/cudnn_version.h"
#include "tensorflow/stream_executor/dnn.h"
#include "tensorflow/stream_executor/lib/env.h"
#include "tensorflow/stream_executor/lib/error.h"
return narrow;
}
-// Returns the "Compatibility" version number from the CuDNN version number.
-// This is the number that tries to indicate ABI compatibility.
-//
-// For example, if cudnn_version is 5107, the compatibility version
-// number will be 5100.
-size_t cudnnCompatibilityVersion(size_t cudnn_version) {
- return (cudnn_version / 100) * 100;
-}
-
} // namespace
namespace perftools {
}
}
+#if CUDNN_VERSION >= 6000
+string ToString(libraryPropertyType type) {
+ switch (type) {
+ case MAJOR_VERSION:
+ return "MAJOR_VERSION";
+ case MINOR_VERSION:
+ return "MINOR_VERSION";
+ case PATCH_LEVEL:
+ return "PATCH_LEVEL";
+ default:
+ return absl::StrCat(
+ "<unknown libraryPropertyType: ", static_cast<int>(type), ">");
+ }
+}
+#endif
+
template <typename T>
cudnnDataType_t GetCudnnDataType();
}
}
+#if CUDNN_VERSION >= 6000
+port::Status GetCudnnProperty(libraryPropertyType type, int* value) {
+ cudnnStatus_t status = cudnnGetProperty(type, value);
+ if (status != CUDNN_STATUS_SUCCESS) {
+ const string error =
+ absl::StrCat("cudnnGetProperty failed for type: ", ToString(type),
+ " with status: ", ToString(status));
+ LOG(ERROR) << error;
+ return port::Status{port::error::INTERNAL, error};
+ }
+ return port::Status::OK();
+}
+#endif
+
+port::Status GetLoadedCudnnVersion(CudnnVersion* version) {
+#if CUDNN_VERSION >= 6000
+ TF_RETURN_IF_ERROR(GetCudnnProperty(MAJOR_VERSION, &version->major_version));
+ TF_RETURN_IF_ERROR(GetCudnnProperty(MINOR_VERSION, &version->minor_version));
+ TF_RETURN_IF_ERROR(GetCudnnProperty(PATCH_LEVEL, &version->patch_level));
+#else
+ size_t loaded_version = ::cudnnGetVersion();
+ version->major_version = loaded_version / 1000;
+ version->minor_version = (loaded_version / 100) % 10;
+ version->patch_level = loaded_version % 100;
+#endif
+ return port::Status::OK();
+}
+
} // namespace
CudnnSupport::CudnnSupport(CUDAExecutor* parent)
auto status = wrap::cudnnCreate(
parent_, reinterpret_cast<cudnnHandle_t*>(&dnn_handle_));
if (status == CUDNN_STATUS_SUCCESS) {
- // Check whether loaded version of CuDNN matches what the source
- // was built with.
- size_t loaded_version = ::cudnnGetVersion();
- size_t loaded_compat_version = cudnnCompatibilityVersion(loaded_version);
- size_t compiled_compat_version = cudnnCompatibilityVersion(CUDNN_VERSION);
- bool library_loaded_matches_source =
- (loaded_compat_version == compiled_compat_version);
- if (!library_loaded_matches_source) {
- const string error =
- port::StrCat("Loaded runtime CuDNN library: ", loaded_version,
- " (compatibility version ", loaded_compat_version,
- ") but source was compiled with ", CUDNN_VERSION,
- " (compatibility version ", compiled_compat_version,
- "). If using a binary install, upgrade your CuDNN "
- "library to match. If building from sources, "
- "make sure the library loaded at runtime matches a "
- "compatible version specified during compile "
- "configuration.");
+ CudnnVersion source_version(CUDNN_MAJOR, CUDNN_MINOR, CUDNN_PATCHLEVEL);
+
+ CudnnVersion loaded_version;
+ TF_RETURN_IF_ERROR(GetLoadedCudnnVersion(&loaded_version));
+ if (!IsSourceCompatibleWithCudnnLibrary(source_version, loaded_version)) {
+ const tensorflow::string error = absl::StrCat(
+ "Loaded runtime CuDNN library: ", loaded_version.ToString(),
+ " but source was compiled with: ", source_version.ToString(),
+ ". CuDNN library major and minor version needs to match or have "
+ "higher minor version in case of CuDNN 7.0 or later version. If "
+ "using a binary install, upgrade your CuDNN library. If building "
+ "from sources, make sure the library loaded at runtime is compatible "
+ "with the version specified during compile configuration.");
LOG(ERROR) << error;
return port::Status{port::error::INTERNAL, error};
}
--- /dev/null
+/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#include "tensorflow/stream_executor/cuda/cudnn_version.h"
+
+namespace perftools {
+namespace gputools {
+namespace cuda {
+
+bool IsSourceCompatibleWithCudnnLibrary(CudnnVersion source_version,
+ CudnnVersion loaded_version) {
+ // Major version is neither forward or backward compatible and therefore major
+ // versions needs to match between source and library.
+ //
+ // Minor version is backward-compatible beginning with CuDNN 7 and therefore
+ // minor version of library needs to be same or higher.
+ //
+ // Patch releases are always forward and backward compatible and therefore
+ // need not match.
+ if (loaded_version.major_version != source_version.major_version) {
+ return false;
+ }
+ return ((loaded_version.minor_version == source_version.minor_version) ||
+ (source_version.major_version >= 7 &&
+ loaded_version.minor_version >= source_version.minor_version));
+}
+
+} // namespace cuda
+} // namespace gputools
+} // namespace perftools
--- /dev/null
+/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#ifndef TENSORFLOW_STREAM_EXECUTOR_CUDA_CUDNN_VERSION_H_
+#define TENSORFLOW_STREAM_EXECUTOR_CUDA_CUDNN_VERSION_H_
+
+#include <string>
+
+#include "absl/strings/str_join.h"
+
+namespace perftools {
+namespace gputools {
+namespace cuda {
+
+struct CudnnVersion {
+ CudnnVersion() = default;
+
+ CudnnVersion(int major, int minor, int patch)
+ : major_version(major), minor_version(minor), patch_level(patch) {}
+
+ std::string ToString() const {
+ return absl::StrJoin({major_version, minor_version, patch_level}, ".");
+ }
+
+ int major_version;
+ int minor_version;
+ int patch_level;
+};
+
+// Returns true if the given source CuDNN version is compatible with the given
+// loaded version.
+bool IsSourceCompatibleWithCudnnLibrary(CudnnVersion source_version,
+ CudnnVersion loaded_version);
+
+} // namespace cuda
+} // namespace gputools
+} // namespace perftools
+
+#endif // TENSORFLOW_STREAM_EXECUTOR_CUDA_CUDNN_VERSION_H_
--- /dev/null
+/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#include "tensorflow/stream_executor/cuda/cudnn_version.h"
+
+#include "testing/base/public/gunit.h"
+#include "tensorflow/core/platform/test.h"
+
+namespace perftools {
+namespace gputools {
+namespace cuda {
+namespace {
+
+TEST(CuDNNVersion, ToString) {
+ CudnnVersion version(7, 0, 12);
+ EXPECT_EQ(version.ToString(), "7.0.12");
+}
+
+TEST(IsSourceCompatibleWithCudnnLibraryTest, Basic) {
+ // Returns true if both major and minor versions are matching and even if the
+ // patch versions are not matching.
+ EXPECT_TRUE(IsSourceCompatibleWithCudnnLibrary(
+ /*source_version=*/CudnnVersion(7, 0, 12),
+ /*loaded_version=*/CudnnVersion(7, 0, 14)));
+ EXPECT_TRUE(IsSourceCompatibleWithCudnnLibrary(
+ /*source_version=*/CudnnVersion(6, 1, 14),
+ /*loaded_version=*/CudnnVersion(6, 1, 00)));
+
+ // Returns false if major versions are not matching as they are neither
+ // forward or backward compatible.
+ EXPECT_FALSE(IsSourceCompatibleWithCudnnLibrary(
+ /*source_version=*/CudnnVersion(7, 0, 12),
+ /*loaded_version=*/CudnnVersion(6, 1, 14)));
+ EXPECT_FALSE(IsSourceCompatibleWithCudnnLibrary(
+ /*source_version=*/CudnnVersion(8, 1, 15),
+ /*loaded_version=*/CudnnVersion(7, 0, 14)));
+
+ // Returns true if the loaded version is equal or higher because minor version
+ // are backward compatible with CuDNN version 7.
+ EXPECT_TRUE(IsSourceCompatibleWithCudnnLibrary(
+ /*source_version=*/CudnnVersion(7, 0, 14),
+ /*loaded_version=*/CudnnVersion(7, 1, 14)));
+ EXPECT_TRUE(IsSourceCompatibleWithCudnnLibrary(
+ /*source_version=*/CudnnVersion(7, 0, 14),
+ /*loaded_version=*/CudnnVersion(7, 1, 15)));
+ EXPECT_FALSE(IsSourceCompatibleWithCudnnLibrary(
+ /*source_version=*/CudnnVersion(7, 1, 15),
+ /*loaded_version=*/CudnnVersion(7, 0, 14)));
+
+ // Returns false if minor versions are not matching for version 6. Before
+ // version 7, minor versions are also neither forward or backward compatible.
+ EXPECT_FALSE(IsSourceCompatibleWithCudnnLibrary(
+ /*source_version=*/CudnnVersion(6, 0, 14),
+ /*loaded_version=*/CudnnVersion(6, 1, 15)));
+ EXPECT_FALSE(IsSourceCompatibleWithCudnnLibrary(
+ /*source_version=*/CudnnVersion(6, 1, 14),
+ /*loaded_version=*/CudnnVersion(6, 0, 14)));
+}
+
+} // namespace
+} // namespace cuda
+} // namespace gputools
+} // namespace perftools