Home | History | Annotate | Download | only in util
      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 #ifndef TENSORFLOW_CORE_UTIL_CUDA_KERNEL_HELPER_H_
     17 #define TENSORFLOW_CORE_UTIL_CUDA_KERNEL_HELPER_H_
     18 
     19 #if GOOGLE_CUDA
     20 
     21 #include "tensorflow/core/util/cuda_device_functions.h"
     22 #include "tensorflow/core/util/cuda_launch_config.h"
     23 
     24 #include "cuda/include/cuda_fp16.h"
     25 
     26 // Deprecated, use 'for(int i : CudaGridRangeX(n))' instead.
     27 #define CUDA_1D_KERNEL_LOOP(i, n) \
     28   for (int i : ::tensorflow::CudaGridRangeX<int>(n))
     29 // Deprecated, use 'for(int i : CudaGridRange?(n))' instead.
     30 #define CUDA_AXIS_KERNEL_LOOP(i, n, axis) \
     31   for (int i : ::tensorflow::CudaGridRange##axis<int>(n))
     32 
     33 namespace tensorflow {
     34 __host__ __device__ inline tensorflow::bfloat16 CudaLdg(
     35     const tensorflow::bfloat16* address) {
     36   tensorflow::bfloat16 return_value;
     37   return_value.value = CudaLdg(reinterpret_cast<const uint16_t*>(address));
     38   return return_value;
     39 }
     40 
     41 template <typename T>
     42 __host__ __device__ inline T ldg(const T* ptr) {
     43   return CudaLdg(ptr);
     44 }
     45 
     46 template <typename T>
     47 __host__ __device__ inline const T& tf_min(const T& x, const T& y) {
     48   return x < y ? x : y;
     49 }
     50 
     51 template <typename T>
     52 __host__ __device__ inline const T& tf_max(const T& x, const T& y) {
     53   return x < y ? y : x;
     54 }
     55 
     56 // Overloads of the above functions for float and double.
     57 __host__ __device__ inline float tf_min(float x, float y) {
     58   return fminf(x, y);
     59 }
     60 __host__ __device__ inline double tf_min(double x, double y) {
     61   return fmin(x, y);
     62 }
     63 __host__ __device__ inline float tf_max(float x, float y) {
     64   return fmaxf(x, y);
     65 }
     66 __host__ __device__ inline double tf_max(double x, double y) {
     67   return fmax(x, y);
     68 }
     69 
     70 __device__ inline Eigen::half CudaShuffleSync(unsigned mask, Eigen::half value,
     71                                               int src_lane,
     72                                               int width = warpSize) {
     73   return Eigen::half(
     74       CudaShuffleSync(mask, static_cast<uint16>(value), src_lane, width));
     75 }
     76 
     77 __device__ EIGEN_ALWAYS_INLINE Eigen::half CudaShuffleUpSync(
     78     unsigned mask, Eigen::half value, int delta, int width = warpSize) {
     79   return Eigen::half(
     80       CudaShuffleUpSync(mask, static_cast<uint16>(value), delta, width));
     81 }
     82 
     83 __device__ EIGEN_ALWAYS_INLINE Eigen::half CudaShuffleDownSync(
     84     unsigned mask, Eigen::half value, int delta, int width = warpSize) {
     85   return Eigen::half(
     86       CudaShuffleDownSync(mask, static_cast<uint16>(value), delta, width));
     87 }
     88 
     89 __device__ EIGEN_ALWAYS_INLINE Eigen::half CudaShuffleXorSync(
     90     unsigned mask, Eigen::half value, int lane_mask, int width = warpSize) {
     91   return Eigen::half(
     92       CudaShuffleXorSync(mask, static_cast<uint16>(value), lane_mask, width));
     93 }
     94 
     95 namespace cuda_helper {
     96 template <typename T, typename OutType = int32>
     97 __device__ OutType upper_bound(const T* first, OutType count, T val) {
     98   const T* orig = first;
     99   const T* it = nullptr;
    100   OutType step = 0;
    101   while (count > 0) {
    102     it = first;
    103     step = count / 2;
    104     it += step;
    105     if (!(val < *it)) {
    106       first = ++it;
    107       count -= step + 1;
    108     } else {
    109       count = step;
    110     }
    111   }
    112 
    113   return first - orig;
    114 }
    115 
    116 template <typename T, typename OutType = int32>
    117 __device__ OutType lower_bound(const T* first, OutType count, T val) {
    118   const T* orig = first;
    119   const T* it = nullptr;
    120   OutType step = 0;
    121   while (count > 0) {
    122     it = first;
    123     step = count / 2;
    124     it += step;
    125     if (*it < val) {
    126       first = ++it;
    127       count -= step + 1;
    128     } else {
    129       count = step;
    130     }
    131   }
    132 
    133   return first - orig;
    134 }
    135 
    136 }  // namespace cuda_helper
    137 }  // namespace tensorflow
    138 
    139 #endif  // GOOGLE_CUDA
    140 #endif  // TENSORFLOW_CORE_UTIL_CUDA_KERNEL_HELPER_H_
    141