1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved. 2 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 ==============================================================================*/ 15 16 #if GOOGLE_CUDA 17 #define EIGEN_USE_GPU 18 19 #include <assert.h> 20 #include <stdio.h> 21 22 #include <math.h> 23 #include <algorithm> 24 25 #include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor" 26 #include "tensorflow/core/platform/types.h" 27 28 namespace tensorflow { 29 30 namespace { 31 32 typedef Eigen::GpuDevice GPUDevice; 33 34 // A Cuda kernel to check if each element is Inf or Nan. If any exists, the 35 // relevant elements in abnormal_detected will be set 36 template <typename T> 37 __global__ void CheckNumericsKernel(const T *data, int size, 38 int abnormal_detected[2]) { 39 const int32 thread_id = blockIdx.x * blockDim.x + threadIdx.x; 40 const int32 total_thread_count = gridDim.x * blockDim.x; 41 42 int32 offset = thread_id; 43 44 while (offset < size) { 45 if (isnan(data[offset])) { 46 abnormal_detected[0] = 1; 47 } 48 if (isinf(data[offset])) { 49 abnormal_detected[1] = 1; 50 } 51 offset += total_thread_count; 52 } 53 } 54 55 } // namespace 56 57 // A simple launch pad to launch the Cuda kernels that checks the numerical 58 // abnormality in the given array 59 template <typename T> 60 struct CheckNumericsLaunch { 61 void Run(const GPUDevice &d, const T *data, int size, 62 int abnormal_detected[2]) { 63 const int32 block_size = d.maxCudaThreadsPerBlock(); 64 const int32 num_blocks = 65 (d.getNumCudaMultiProcessors() * d.maxCudaThreadsPerMultiProcessor()) / 66 block_size; 67 68 CheckNumericsKernel<T><<<num_blocks, block_size, 0, d.stream()>>>( 69 data, size, abnormal_detected); 70 } 71 }; 72 73 template struct CheckNumericsLaunch<Eigen::half>; 74 template struct CheckNumericsLaunch<float>; 75 template struct CheckNumericsLaunch<double>; 76 77 } // namespace tensorflow 78 #endif // GOOGLE_CUDA 79