1*da0073e9SAndroid Build Coastguard Worker# csrc 2*da0073e9SAndroid Build Coastguard Worker 3*da0073e9SAndroid Build Coastguard WorkerThe csrc directory contains all of the code concerned with integration 4*da0073e9SAndroid Build Coastguard Workerwith Python. This is in contrast to lib, which contains the Torch 5*da0073e9SAndroid Build Coastguard Workerlibraries that are Python agnostic. csrc depends on lib, but not vice 6*da0073e9SAndroid Build Coastguard Workerversa. 7*da0073e9SAndroid Build Coastguard Worker 8*da0073e9SAndroid Build Coastguard WorkerThere are a number of utilities for easing integration with Python which 9*da0073e9SAndroid Build Coastguard Workerare worth knowing about, which we briefly describe here. But the most 10*da0073e9SAndroid Build Coastguard Workerimportant gotchas: 11*da0073e9SAndroid Build Coastguard Worker 12*da0073e9SAndroid Build Coastguard Worker* DO NOT forget to take out the GIL with `pybind11::gil_scoped_acquire` 13*da0073e9SAndroid Build Coastguard Worker before calling Python API or bringing a `THPObjectPtr` into scope. 14*da0073e9SAndroid Build Coastguard Worker 15*da0073e9SAndroid Build Coastguard Worker* Make sure you include `Python.h` first in your header files, before 16*da0073e9SAndroid Build Coastguard Worker any system headers; otherwise, you will get `error: "_XOPEN_SOURCE" redefined` 17*da0073e9SAndroid Build Coastguard Worker error. If you pay attention to warnings, you will see where you need to 18*da0073e9SAndroid Build Coastguard Worker do this. 19*da0073e9SAndroid Build Coastguard Worker 20*da0073e9SAndroid Build Coastguard Worker## Notes 21*da0073e9SAndroid Build Coastguard Worker 22*da0073e9SAndroid Build Coastguard Worker### Note [Storage is not nullptr] 23*da0073e9SAndroid Build Coastguard Worker 24*da0073e9SAndroid Build Coastguard WorkerHistorically, Torch supported nullptr storage, as a minor optimization to 25*da0073e9SAndroid Build Coastguard Workeravoid having to allocate a storage object when it would be empty. 26*da0073e9SAndroid Build Coastguard WorkerHowever, this is actually a confusing special case to deal with, so 27*da0073e9SAndroid Build Coastguard Workerby-in-large, PyTorch assumes that, in fact, storage is never nullptr. 28*da0073e9SAndroid Build Coastguard Worker 29*da0073e9SAndroid Build Coastguard WorkerOne important case where this assumption is important is when tracking 30*da0073e9SAndroid Build Coastguard Workerthe CUDA device a tensor is stored in: this information is stored 31*da0073e9SAndroid Build Coastguard Workersolely in the storage, so if a storage is nullptr, we lose this information. 32*da0073e9SAndroid Build Coastguard Worker 33*da0073e9SAndroid Build Coastguard WorkerAlthough storage is never nullptr, the data field of c10::StorageImpl may be 34*da0073e9SAndroid Build Coastguard Workernullptr. This 35*da0073e9SAndroid Build Coastguard Workermostly occurs when we want to pre-allocate an output tensor struct, but then 36*da0073e9SAndroid Build Coastguard Workerhave it be resized and filled with data by some operator: there's no point in 37*da0073e9SAndroid Build Coastguard Workerallocating data for it in this case! 38*da0073e9SAndroid Build Coastguard Worker 39*da0073e9SAndroid Build Coastguard Worker## Files 40*da0073e9SAndroid Build Coastguard Worker 41*da0073e9SAndroid Build Coastguard Worker### `Exceptions.h` 42*da0073e9SAndroid Build Coastguard Worker 43*da0073e9SAndroid Build Coastguard WorkerFrequently when working with the Python API, you may call a function 44*da0073e9SAndroid Build Coastguard Workerwhich returns an error. In this case, we want to return directly to the 45*da0073e9SAndroid Build Coastguard WorkerPython interpreter, so that this exception can be propagated 46*da0073e9SAndroid Build Coastguard Workeraccordingly; however, because the Python API is C-based, what actually 47*da0073e9SAndroid Build Coastguard Workerwill happen is it will return control to whatever C++ code called it. 48*da0073e9SAndroid Build Coastguard WorkerSimilarly, if we raise a C++ exception, prior to returning to the Python 49*da0073e9SAndroid Build Coastguard Workerinterpreter, we must set the Python error flags, so it turns into a C++ 50*da0073e9SAndroid Build Coastguard Workerexception. 51*da0073e9SAndroid Build Coastguard Worker 52*da0073e9SAndroid Build Coastguard WorkerMoreover, when using the following macros, the generated warnings 53*da0073e9SAndroid Build Coastguard Workerwill be converted into python warnings that can be caught by the user. 54*da0073e9SAndroid Build Coastguard Worker 55*da0073e9SAndroid Build Coastguard WorkerExceptions define helpers for two main cases: 56*da0073e9SAndroid Build Coastguard Worker* For code where you write the python binding by hand, `HANDLE_TH_ERRORS`, 57*da0073e9SAndroid Build Coastguard Worker`END_HANDLE_TH_ERRORS` and an exception class `python_error`. You call them like this: 58*da0073e9SAndroid Build Coastguard Worker 59*da0073e9SAndroid Build Coastguard Worker``` 60*da0073e9SAndroid Build Coastguard Worker// Entry point from Python interpreter 61*da0073e9SAndroid Build Coastguard WorkerPyObject* run(PyObject* arg) { 62*da0073e9SAndroid Build Coastguard Worker HANDLE_TH_ERRORS 63*da0073e9SAndroid Build Coastguard Worker ... 64*da0073e9SAndroid Build Coastguard Worker if (!x) throw python_error(); 65*da0073e9SAndroid Build Coastguard Worker // From c10/Exception.h 66*da0073e9SAndroid Build Coastguard Worker TORCH_CHECK(cond, "cond was false here"); 67*da0073e9SAndroid Build Coastguard Worker TORCH_WARN("Warning message"); 68*da0073e9SAndroid Build Coastguard Worker ... 69*da0073e9SAndroid Build Coastguard Worker END_HANDLE_TH_ERRORS 70*da0073e9SAndroid Build Coastguard Worker} 71*da0073e9SAndroid Build Coastguard Worker``` 72*da0073e9SAndroid Build Coastguard Worker 73*da0073e9SAndroid Build Coastguard WorkerThe `HANDLE_TH_ERRORS` macro will catch all exceptions and convert them 74*da0073e9SAndroid Build Coastguard Workerinto an appropriate Python signal. `python_error` is a special 75*da0073e9SAndroid Build Coastguard Workerexception which doesn't contain any info, instead it says, "An error 76*da0073e9SAndroid Build Coastguard Workeroccurred in the Python API; if you return to the interpreter, Python 77*da0073e9SAndroid Build Coastguard Workerwill raise that exception, nothing else needs to be done." 78*da0073e9SAndroid Build Coastguard Worker 79*da0073e9SAndroid Build Coastguard Worker* For code that you bind using pybind, `HANDLE_TH_ERRORS` and `END_HANDLE_TH_ERRORS_PYBIND` 80*da0073e9SAndroid Build Coastguard Workercan be used. They will work jointly with pybind error handling to raise 81*da0073e9SAndroid Build Coastguard Workerpytorch errors and warnings natively and let pybind handle other errors. It can be used as: 82*da0073e9SAndroid Build Coastguard Worker 83*da0073e9SAndroid Build Coastguard Worker``` 84*da0073e9SAndroid Build Coastguard Worker// Function given to the pybind binding 85*da0073e9SAndroid Build Coastguard Workerat::Tensor foo(at::Tensor x) { 86*da0073e9SAndroid Build Coastguard Worker HANDLE_TH_ERRORS 87*da0073e9SAndroid Build Coastguard Worker ... 88*da0073e9SAndroid Build Coastguard Worker if (!x) throw python_error(); 89*da0073e9SAndroid Build Coastguard Worker // pybind native error 90*da0073e9SAndroid Build Coastguard Worker if (!x) throw py::value_error(); 91*da0073e9SAndroid Build Coastguard Worker // From c10/Exception.h 92*da0073e9SAndroid Build Coastguard Worker TORCH_CHECK(cond, "cond was false here"); 93*da0073e9SAndroid Build Coastguard Worker TORCH_WARN("Warning message"); 94*da0073e9SAndroid Build Coastguard Worker ... 95*da0073e9SAndroid Build Coastguard Worker END_HANDLE_TH_ERRORS_PYBIND 96*da0073e9SAndroid Build Coastguard Worker} 97*da0073e9SAndroid Build Coastguard Worker``` 98*da0073e9SAndroid Build Coastguard Worker 99*da0073e9SAndroid Build Coastguard Worker 100*da0073e9SAndroid Build Coastguard Worker### GIL 101*da0073e9SAndroid Build Coastguard Worker 102*da0073e9SAndroid Build Coastguard WorkerWhenever you make any calls to the Python API, you must have taken out 103*da0073e9SAndroid Build Coastguard Workerthe Python GIL, as none of these calls are thread safe. 104*da0073e9SAndroid Build Coastguard Worker`pybind11::gil_scoped_acquire` is a RAII struct which handles taking and 105*da0073e9SAndroid Build Coastguard Workerreleasing the GIL. Use it like this: 106*da0073e9SAndroid Build Coastguard Worker 107*da0073e9SAndroid Build Coastguard Worker``` 108*da0073e9SAndroid Build Coastguard Workervoid iWantToUsePython() { 109*da0073e9SAndroid Build Coastguard Worker pybind11::gil_scoped_acquire gil; 110*da0073e9SAndroid Build Coastguard Worker ... 111*da0073e9SAndroid Build Coastguard Worker} 112*da0073e9SAndroid Build Coastguard Worker``` 113*da0073e9SAndroid Build Coastguard Worker 114*da0073e9SAndroid Build Coastguard WorkerIn general, the compiler will NOT warn you if you use Python 115*da0073e9SAndroid Build Coastguard Workerfunctionality without taking out the GIL, so DO NOT FORGET this call. 116*da0073e9SAndroid Build Coastguard Worker 117*da0073e9SAndroid Build Coastguard Worker### `utils/object_ptr.h` 118*da0073e9SAndroid Build Coastguard Worker 119*da0073e9SAndroid Build Coastguard Worker`THPPointer` is a smart pointer class analogous to `std::shared_ptr`, 120*da0073e9SAndroid Build Coastguard Workerbut which is overloaded to handle reference counting scheme of various 121*da0073e9SAndroid Build Coastguard Workerobjects which are not based on `shared_ptr`. The most important overloads are: 122*da0073e9SAndroid Build Coastguard Worker 123*da0073e9SAndroid Build Coastguard Worker* `PyObject` (so important we've aliased it as `THPObjectPtr`), which 124*da0073e9SAndroid Build Coastguard Worker hooks into Python reference counting. (By the way, that means you 125*da0073e9SAndroid Build Coastguard Worker MUST take out the GIL before bringing one of these into scope!) 126*da0073e9SAndroid Build Coastguard Worker 127*da0073e9SAndroid Build Coastguard Worker* The various TH tensor and storage types (e.g., `THTensor`), which 128*da0073e9SAndroid Build Coastguard Worker hook into TH's reference counting. (TH's reference counting 129*da0073e9SAndroid Build Coastguard Worker IS thread safe, no locks necessary.) 130