Caffe2 - C++ API
A deep learning, cross platform ML framework
Descriptors.cpp
1 #include <ATen/cudnn/Descriptors.h>
2 
3 #include <ATen/ATen.h>
4 
5 #include <ostream>
6 #include <sstream>
7 #include <string>
8 
9 namespace at { namespace native {
10 
11 namespace {
12 
13 inline cudnnDataType_t getDataType(const at::Tensor& t) {
14  auto scalar_type = t.scalar_type();
15  if (scalar_type == at::kFloat) {
16  return CUDNN_DATA_FLOAT;
17  } else if (scalar_type == at::kHalf) {
18  return CUDNN_DATA_HALF;
19  } else if (scalar_type == at::kDouble) {
20  return CUDNN_DATA_DOUBLE;
21  }
22  throw std::runtime_error("TensorDescriptor only supports double, float and half tensors");
23 }
24 
25 } // anonymous namespace
26 
27 
28 void TensorDescriptor::set(const at::Tensor &t, size_t pad) {
29  set(getDataType(t), t.sizes(), t.strides(), pad);
30 }
31 
32 void TensorDescriptor::set(cudnnDataType_t datatype, IntArrayRef t_sizes, IntArrayRef t_strides, size_t pad) {
33  size_t dim = t_sizes.size();
34  if (dim > CUDNN_DIM_MAX || pad > CUDNN_DIM_MAX)
35 #define _STR(X) #X
36 #define STR(X) _STR(X)
37  throw std::runtime_error("cuDNN supports only up to " STR(CUDNN_DIM_MAX) " dimensions");
38 #undef _STR
39 #undef STR
40  int size[CUDNN_DIM_MAX];
41  int stride[CUDNN_DIM_MAX];
42  for (size_t i = 0; i < dim; ++i) {
43  size[i] = static_cast<int>(t_sizes[i]);
44  stride[i] = static_cast<int>(t_strides[i]);
45  }
46  for (size_t i = dim; i < pad; ++i) {
47  size[i] = 1;
48  stride[i] = 1;
49  }
50  set(datatype, static_cast<int>(std::max(dim, pad)), size, stride);
51 }
52 
53 std::string cudnnTypeToString(cudnnDataType_t dtype) {
54  switch (dtype) {
55  case CUDNN_DATA_FLOAT:
56  return "CUDNN_DATA_FLOAT";
57  case CUDNN_DATA_DOUBLE:
58  return "CUDNN_DATA_DOUBLE";
59  case CUDNN_DATA_HALF:
60  return "CUDNN_DATA_HALF";
61  case CUDNN_DATA_INT8:
62  return "CUDNN_DATA_INT8";
63  case CUDNN_DATA_INT32:
64  return "CUDNN_DATA_INT32";
65  case CUDNN_DATA_INT8x4:
66  return "CUDNN_DATA_INT8x4";
67 #if CUDNN_VERSION >= 7100
68  case CUDNN_DATA_UINT8:
69  return "CUDNN_DATA_UINT8";
70  case CUDNN_DATA_UINT8x4:
71  return "CUDNN_DATA_UINT8x4";
72 #endif
73  default:
74  std::ostringstream oss;
75  oss << "(unknown data-type " << static_cast<int>(dtype) << ")";
76  return oss.str();
77  }
78 }
79 
80 std::ostream& operator<<(std::ostream & out, const TensorDescriptor& d) {
81  out << "TensorDescriptor " << static_cast<void*>(d.desc()) << "\n";
82  int nbDims;
83  int dimA[CUDNN_DIM_MAX];
84  int strideA[CUDNN_DIM_MAX];
85  cudnnDataType_t dtype;
86  cudnnGetTensorNdDescriptor(d.desc(), CUDNN_DIM_MAX, &dtype, &nbDims, dimA, strideA);
87  out << " type = " << cudnnTypeToString(dtype) << "\n";
88  out << " nbDims = " << nbDims << "\n";
89  // Read out only nbDims of the arrays!
90  out << " dimA = ";
91  for (auto i : ArrayRef<int>{dimA, static_cast<size_t>(nbDims)}) {
92  out << i << ", ";
93  }
94  out << "\n";
95  out << " strideA = ";
96  for (auto i : ArrayRef<int>{strideA, static_cast<size_t>(nbDims)}) {
97  out << i << ", ";
98  }
99  out << "\n";
100  return out;
101 }
102 
103 void TensorDescriptor::print() { std::cout << *this; }
104 
105 void FilterDescriptor::set(const at::Tensor &t, int64_t pad) {
106  auto dim = t.ndimension();
107  if (dim > CUDNN_DIM_MAX || pad > CUDNN_DIM_MAX)
108 #define _STR(X) #X
109 #define STR(X) _STR(X)
110  throw std::runtime_error("cuDNN supports only up to " STR(CUDNN_DIM_MAX) " dimensions");
111 #undef _STR
112 #undef STR
113  if (!t.is_contiguous()) {
114  // NB: It is possible for this test to be insufficient, because the
115  // Tensor passed in to set the filter descriptor may not be the actual
116  // Tensor whose data pointer is passed to cuDNN. Nevertheless,
117  // that is the common case, so we can catch most client errors with this test.
118  throw std::runtime_error("cuDNN filters (a.k.a. weights) must be contiguous");
119  }
120  int size[CUDNN_DIM_MAX];
121  for (int i = 0; i < dim; ++i) {
122  size[i] = (int) t.size(i);
123  }
124  for (int i = dim; i < pad; ++i) {
125  size[i] = (int) 1;
126  }
127  dim = std::max(dim, pad);
128  set(getDataType(t), (int) dim, size);
129 }
130 
131 }}
Flush-To-Zero and Denormals-Are-Zero mode.