Home | History | Annotate | Download | only in kernels
      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