1122cdce33e3e0a01a7f82645617317530aa571fbA. Unique TensorFlower/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
29c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudlur
39c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath KudlurLicensed under the Apache License, Version 2.0 (the "License");
49c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudluryou may not use this file except in compliance with the License.
59c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath KudlurYou may obtain a copy of the License at
69c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudlur
79c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudlur    http://www.apache.org/licenses/LICENSE-2.0
89c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudlur
99c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath KudlurUnless required by applicable law or agreed to in writing, software
109c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudlurdistributed under the License is distributed on an "AS IS" BASIS,
119c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath KudlurWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
129c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath KudlurSee the License for the specific language governing permissions and
139c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudlurlimitations under the License.
149c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudlur==============================================================================*/
159c3043ff3bf31a6a81810b4ce9e87ef936f1f529Manjunath Kudlur
16f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur#include "tensorflow/stream_executor/cuda/cuda_platform.h"
17f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
18f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur#include "tensorflow/stream_executor/cuda/cuda_driver.h"
19ddd4aaf5286de24ba70402ee0ec8b836d3aed8c7Vijay Vasudevan#include "tensorflow/stream_executor/cuda/cuda_gpu_executor.h"
20ddd4aaf5286de24ba70402ee0ec8b836d3aed8c7Vijay Vasudevan#include "tensorflow/stream_executor/cuda/cuda_platform_id.h"
21f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur#include "tensorflow/stream_executor/lib/error.h"
22f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur#include "tensorflow/stream_executor/lib/initialize.h"
23f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur#include "tensorflow/stream_executor/lib/ptr_util.h"
24f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur#include "tensorflow/stream_executor/lib/status.h"
25f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur#include "tensorflow/stream_executor/lib/stringprintf.h"
26f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
27f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlurnamespace perftools {
28f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlurnamespace gputools {
29f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlurnamespace cuda {
30109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlowernamespace {
31109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower
32109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower// Synchronize with spinlocks.
33109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlowerconst char kScheduleSpinString[] = "spin";
34109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower// Synchronize with spinlocks that also call CPU yield instructions.
35109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlowerconst char kScheduleYieldString[] = "yield";
36109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower// Synchronize with a "synchronization primitive" (e.g. mutex).
37109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlowerconst char kScheduleBlockingSyncString[] = "blocking_sync";
38109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower
39109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlowerconst DeviceOptions GetDeviceOptionsFromEnv() {
40109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower  const char* gpu_schedule_string =
41109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower      std::getenv("TF_CUDA_PLATFORM_GPU_DEVICE_SCHEDULE");
42109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower
43109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower  if (gpu_schedule_string == nullptr) {
44109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower    return perftools::gputools::DeviceOptions::Default();
45109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower  }
46109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower
47109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower  unsigned device_flags = 0;
489b3233d25e0dd7078667712f128657f3fbb7dbd4A. Unique TensorFlower  if (strcmp(kScheduleSpinString, gpu_schedule_string) == 0) {
49109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower    device_flags = perftools::gputools::DeviceOptions::kScheduleSpin;
509b3233d25e0dd7078667712f128657f3fbb7dbd4A. Unique TensorFlower  } else if (strcmp(kScheduleYieldString, gpu_schedule_string) == 0) {
51109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower    device_flags = perftools::gputools::DeviceOptions::kScheduleYield;
529b3233d25e0dd7078667712f128657f3fbb7dbd4A. Unique TensorFlower  } else if (strcmp(kScheduleBlockingSyncString, gpu_schedule_string) == 0) {
53109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower    device_flags = perftools::gputools::DeviceOptions::kScheduleBlockingSync;
54109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower  } else {
55109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower    LOG(QFATAL) << "Unknown option for environment variable "
56109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower                   "TF_CUDA_PLATFORM_GPU_DEVICE_SCHEDULE "
57109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower                << gpu_schedule_string << " should be one of {"
58109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower                << kScheduleBlockingSyncString << ", " << kScheduleSpinString
59109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower                << ", " << kScheduleYieldString << "}";
60109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower  }
61109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower
62109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower  return perftools::gputools::DeviceOptions(device_flags);
63109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower}
64109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower
65109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower}  // namespace
66f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
67f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath KudlurCudaPlatform::CudaPlatform()
68f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    : name_("CUDA"), min_numa_node_(0), limit_numa_node_(0) {}
69f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
70f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath KudlurCudaPlatform::~CudaPlatform() {}
71f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
72f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur// Due to legacy issues in user code, we can't currently call InpectNumaNodes
73f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur// at module initialization time, because non-GPU programs still include this
74f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur// plugin via various methods, so instead, it has to be init-on-reference.
75f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlurvoid CudaPlatform::InspectNumaNodes() {
76f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  // To get NUMA node information, we need to create all executors, so we can
77f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  // examine their device descriptions to see their bus assignments.
78f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  static bool initialized = false;
79f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  static mutex numa_mutex(LINKER_INITIALIZED);
80f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  mutex_lock lock(numa_mutex);
81f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  if (initialized) {
82f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    return;
83f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  }
84f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
85f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  StreamExecutorConfig config;
86f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  for (int i = 0; i < VisibleDeviceCount(); i++) {
87f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    config.ordinal = i;
88f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    StreamExecutor* exec = GetExecutor(config).ValueOrDie();
89f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    if (i == 0) {
90f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur      // NUMA nodes may not start at 0, so set the minimum node  based on the
91f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur      // first executor we see.
92f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur      min_numa_node_ = exec->GetDeviceDescription().numa_node();
93f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur      limit_numa_node_ = min_numa_node_ + 1;
94f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    } else {
95f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur      min_numa_node_ =
96f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur          std::min(min_numa_node_, exec->GetDeviceDescription().numa_node());
97f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur      limit_numa_node_ = std::max(limit_numa_node_,
98f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur                                  exec->GetDeviceDescription().numa_node() + 1);
99f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    }
100f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  }
101f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  initialized = true;
102f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur}
103f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
104f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlurint CudaPlatform::BusCount() {
105f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  InspectNumaNodes();
106f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  return limit_numa_node_ - min_numa_node_;
107f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur}
108f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
109f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlurint CudaPlatform::DeviceToBus(int device_ordinal) {
110f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  StreamExecutorConfig config;
111f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  config.ordinal = device_ordinal;
112f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  StreamExecutor* exec = GetExecutor(config).ValueOrDie();
113f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  return exec->GetDeviceDescription().numa_node() - min_numa_node_;
114f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur}
115f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
116f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlurport::StatusOr<StreamExecutor*> CudaPlatform::FirstExecutorForBus(
117f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    int bus_ordinal) {
118f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  InspectNumaNodes();
119f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  CHECK_LT(bus_ordinal, BusCount()) << "bus ordinal out of available range";
120f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  for (int i = 0; i < VisibleDeviceCount(); i++) {
121f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    if (DeviceToBus(i) == bus_ordinal) {
122f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur      StreamExecutorConfig config;
123f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur      config.ordinal = i;
124f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur      return GetExecutor(config).ValueOrDie();
125f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    }
126f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  }
127f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
128f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  return port::Status{
129f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur      port::error::NOT_FOUND,
130f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur      port::Printf("Executor for bus %d not found.", bus_ordinal)};
131f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur}
132f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
133f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath KudlurPlatform::Id CudaPlatform::id() const { return kCudaPlatformId; }
134f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
135f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlurint CudaPlatform::VisibleDeviceCount() const {
136f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  // Throw away the result - it logs internally, and this [containing] function
137f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  // isn't in the path of user control. It's safe to call this > 1x.
138f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  if (!cuda::CUDADriver::Init().ok()) {
139f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    return -1;
140f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  }
141f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
142f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  return CUDADriver::GetDeviceCount();
143f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur}
144f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
145f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlurconst string& CudaPlatform::Name() const { return name_; }
146f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
147f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlurport::StatusOr<StreamExecutor*> CudaPlatform::ExecutorForDevice(int ordinal) {
148f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  StreamExecutorConfig config;
149f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  config.ordinal = ordinal;
150f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  config.plugin_config = PluginConfig();
151109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower  config.device_options = GetDeviceOptionsFromEnv();
152f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  return GetExecutor(config);
153f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur}
154f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
155f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlurport::StatusOr<StreamExecutor*> CudaPlatform::ExecutorForDeviceWithPluginConfig(
156f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    int device_ordinal, const PluginConfig& plugin_config) {
157f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  StreamExecutorConfig config;
158f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  config.ordinal = device_ordinal;
159f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  config.plugin_config = plugin_config;
160109133639706026d2bd944dd0a0c8fcae0d4fac6A. Unique TensorFlower  config.device_options = GetDeviceOptionsFromEnv();
161f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  return GetExecutor(config);
162f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur}
163f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
164f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlurport::StatusOr<StreamExecutor*> CudaPlatform::GetExecutor(
165f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    const StreamExecutorConfig& config) {
166122750a879f508342b53ee2eaecfde1656981280Peter Hawkins  return executor_cache_.GetOrCreate(
167122750a879f508342b53ee2eaecfde1656981280Peter Hawkins      config, [&]() { return GetUncachedExecutor(config); });
168f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur}
169f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
170f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlurport::StatusOr<std::unique_ptr<StreamExecutor>>
171f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath KudlurCudaPlatform::GetUncachedExecutor(const StreamExecutorConfig& config) {
172ddd4aaf5286de24ba70402ee0ec8b836d3aed8c7Vijay Vasudevan  auto executor = port::MakeUnique<StreamExecutor>(
173c31294351628addffc1cd89687fad0e81bac5a55A. Unique TensorFlower      this, port::MakeUnique<CUDAExecutor>(config.plugin_config));
174f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  auto init_status = executor->Init(config.ordinal, config.device_options);
175f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  if (!init_status.ok()) {
176f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    return port::Status{
177f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur        port::error::INTERNAL,
178f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur        port::Printf(
179f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur            "failed initializing StreamExecutor for CUDA device ordinal %d: %s",
180f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur            config.ordinal, init_status.ToString().c_str())};
181f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  }
182f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
183f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  return std::move(executor);
184f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur}
185f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
186f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlurvoid CudaPlatform::RegisterTraceListener(
187f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur    std::unique_ptr<TraceListener> listener) {
188f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  LOG(FATAL) << "not yet implemented: register CUDA trace listener";
189f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur}
190f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
191f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlurvoid CudaPlatform::UnregisterTraceListener(TraceListener* listener) {
192f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  LOG(FATAL) << "not yet implemented: unregister CUDA trace listener";
193f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur}
194f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
195f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur}  // namespace cuda
196f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
197f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlurstatic void InitializeCudaPlatform() {
198f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  // Disabling leak checking, MultiPlatformManager does not destroy its
199f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  // registered platforms.
200191825e63f341a4e7777b85254f616e541000d5cA. Unique TensorFlower
201f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  std::unique_ptr<cuda::CudaPlatform> platform(new cuda::CudaPlatform);
202f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur  SE_CHECK_OK(MultiPlatformManager::RegisterPlatform(std::move(platform)));
203f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur}
204f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
205f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur}  // namespace gputools
206f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur}  // namespace perftools
207f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur
208f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath KudlurREGISTER_MODULE_INITIALIZER(cuda_platform,
209f41959ccb2d9d4c722fe8fc3351401d53bcf490Manjunath Kudlur                            perftools::gputools::InitializeCudaPlatform());
210a7b60a8206554270c1d066fd66242b1d90574a14A. Unique TensorFlower
211a7b60a8206554270c1d066fd66242b1d90574a14A. Unique TensorFlowerDECLARE_MODULE_INITIALIZER(multi_platform_manager);
212a7b60a8206554270c1d066fd66242b1d90574a14A. Unique TensorFlower// Note that module initialization sequencing is not supported in the
213a7b60a8206554270c1d066fd66242b1d90574a14A. Unique TensorFlower// open-source project, so this will be a no-op there.
214a7b60a8206554270c1d066fd66242b1d90574a14A. Unique TensorFlowerREGISTER_MODULE_INITIALIZER_SEQUENCE(cuda_platform, multi_platform_manager);
215