1
// Note(jiayq): the import_array function is done inside
2
// caffe2_python.cc. Read
3
// http://docs.scipy.org/doc/numpy-1.10.1/reference/c-api.array.html#miscellaneous
8
#include "pybind_state.h"
10
#include <pybind11/pybind11.h>
11
#include <pybind11/stl.h>
13
#ifdef CAFFE2_USE_CUDNN
14
#include "caffe2/core/common_cudnn.h"
15
#endif // CAFFE2_USE_CUDNN
16
#include <c10/cuda/CUDAGuard.h>
17
#include "caffe2/core/context_gpu.h"
18
#include "caffe2/operators/operator_fallback_gpu.h"
19
#include "caffe2/python/pybind_state_registry.h"
22
#include "caffe2/contrib/tensorrt/tensorrt_tranformer.h"
23
#endif // CAFFE2_USE_TRT
28
REGISTER_CUDA_OPERATOR(Python, GPUFallbackOp);
29
REGISTER_CUDA_OPERATOR(PythonGradient, GPUFallbackOp);
31
REGISTER_CUDA_OPERATOR(PythonDLPack, GPUFallbackOp);
32
REGISTER_CUDA_OPERATOR(PythonDLPackGradient, GPUFallbackOp);
34
REGISTER_BLOB_FEEDER(CUDA, TensorFeeder<CUDAContext>);
36
namespace py = pybind11;
38
void addCUDAGlobalMethods(py::module& m) {
39
m.def("num_cuda_devices", &NumCudaDevices);
40
m.def("get_cuda_version", &CudaVersion);
41
#ifdef CAFFE2_USE_CUDNN
42
m.def("get_cudnn_version", &cudnnCompiledVersion);
43
m.attr("cudnn_convolution_fwd_algo_count") =
44
py::int_((int)CUDNN_CONVOLUTION_FWD_ALGO_COUNT);
45
m.attr("cudnn_convolution_bwd_data_algo_count") =
46
py::int_((int)CUDNN_CONVOLUTION_BWD_DATA_ALGO_COUNT);
47
m.attr("cudnn_convolution_bwd_filter_algo_count") =
48
py::int_((int)CUDNN_CONVOLUTION_BWD_FILTER_ALGO_COUNT);
50
m.def("get_cudnn_version", []() { return static_cast<size_t>(0); });
51
m.attr("cudnn_convolution_fwd_algo_count") = py::int_(0);
52
m.attr("cudnn_convolution_bwd_data_algo_count") = py::int_(0);
53
m.attr("cudnn_convolution_bwd_filter_algo_count") = py::int_(0);
55
m.def("get_gpu_memory_info", [](int device_id) {
56
CUDAGuard guard(device_id);
57
size_t device_free, device_total;
58
CUDA_CHECK(cudaMemGetInfo(&device_free, &device_total));
59
return std::pair<size_t, size_t>{device_free, device_total};
61
m.def("get_cuda_peer_access_pattern", []() {
62
std::vector<std::vector<bool>> pattern;
63
CAFFE_ENFORCE(caffe2::GetCudaPeerAccessPattern(&pattern));
66
m.def("get_device_properties", [](int deviceid) {
67
auto& prop = GetDeviceProperty(deviceid);
68
std::map<std::string, py::object> obj;
69
obj["name"] = py::cast(prop.name);
70
obj["major"] = py::cast(prop.major);
71
obj["minor"] = py::cast(prop.minor);
72
obj["totalGlobalMem"] = py::cast(prop.totalGlobalMem);
77
[](const py::bytes& onnx_model_str,
78
const std::unordered_map<std::string, std::vector<int>>&
81
int max_workspace_size,
83
bool debug_builder) -> py::bytes {
85
TensorRTTransformer t(
86
max_batch_size, max_workspace_size, verbosity, debug_builder);
88
t.BuildTrtOp(onnx_model_str.cast<std::string>(), output_size_hints);
90
op_def.SerializeToString(&out);
91
return py::bytes(out);
93
CAFFE_THROW("Please build Caffe2 with USE_TENSORRT=1");
94
#endif // CAFFE2_USE_TRT
98
[](const py::bytes& pred_net_str,
99
const std::unordered_map<std::string, std::vector<int>>& shapes,
101
int max_workspace_size,
104
bool build_serializable_op) -> py::bytes {
106
caffe2::NetDef pred_net;
107
if (!ParseProtoFromLargeString(
108
pred_net_str.cast<std::string>(), &pred_net)) {
109
LOG(ERROR) << "broken pred_net protobuf";
111
std::unordered_map<std::string, TensorShape> tensor_shapes;
112
for (const auto& it : shapes) {
113
tensor_shapes.emplace(
114
it.first, CreateTensorShape(it.second, TensorProto::FLOAT));
116
TensorRTTransformer ts(
121
build_serializable_op);
122
ts.Transform(GetCurrentWorkspace(), &pred_net, tensor_shapes);
123
std::string pred_net_str2;
124
pred_net.SerializeToString(&pred_net_str2);
125
return py::bytes(pred_net_str2);
127
CAFFE_THROW("Please build Caffe2 with USE_TENSORRT=1");
128
#endif // CAFFE2_USE_TRT
132
void addCUDAObjectMethods(py::module& m) {
133
py::class_<DLPackWrapper<CUDAContext>>(m, "DLPackTensorCUDA")
134
.def_property_readonly(
136
[](DLPackWrapper<CUDAContext>* t) -> py::object {
138
t->device_option.device_type(),
140
"Expected CUDA device option for CUDA tensor");
144
"Return DLPack tensor with tensor's data.")
147
[](DLPackWrapper<CUDAContext>* t, py::object obj) {
149
t->device_option.device_type(),
151
"Expected CUDA device option for CUDA tensor");
154
"Copy data from given DLPack tensor into this tensor.")
155
.def_property_readonly(
157
[](const DLPackWrapper<CUDAContext>& t) { return t.tensor->sizes(); })
160
[](DLPackWrapper<CUDAContext>* t, std::vector<int64_t> dims) {
161
t->tensor->Resize(dims);
165
PYBIND11_MODULE(caffe2_pybind11_state_gpu, m) {
166
m.doc() = "pybind11 stateful interface to Caffe2 workspaces - GPU edition";
169
addCUDAGlobalMethods(m);
171
addCUDAObjectMethods(m);
172
for (const auto& addition : PybindAdditionRegistry()->Keys()) {
173
PybindAdditionRegistry()->Create(addition, m);