pytorch/torch/csrc
Horace He f81db8afb8 Initial torchbind prototype (#21098)
Summary:
I have some test code in there as well, along with a script "test_libtorch" to run it. You'll need to modify `test_libtorch` to point to where you have `pytorch` built. I currently require that `pybind11` is included as a subdirectory of the test, but added it to the `.gitignore` to make this reviewable.

Currently, something like this works:
```cpp
struct Foo {
  int x, y;
  Foo(): x(2), y(5){}
  Foo(int x_, int y_) : x(x_), y(y_) {}
  void display() {
    cout<<"x: "<<x<<' '<<"y: "<<y<<endl;
  }
  int64_t add(int64_t z) {
    return (x+y)*z;
  }
};
static auto test = torch::jit::class_<Foo>("Foo")
                    .def(torch::jit::init<int64_t, int64_t>())
                    .def("display", &Foo::display)
                    .def("add", &Foo::add)
                    .def("combine", &Foo::combine);

```
with
```py
torch.jit.script
def f(x):
    val = torch._C.Foo(5, 3)
    val.display()
    print(val.add(3))
```
results in
```
x: 5 y: 3
24
```

Current issues:
- [x] The python class created by torchscript doesn't interactly properly with the surrounding code.
```
torch.jit.script
def f(x):
    val = torch._C.Foo(5, 3)
    return val
```
- [x] Doesn't properly take in non-pointer classes. Can't define this function signature in cpp (We don't want to support this I believe).
```cpp
  void combine(Foo x) {
```

- [x] Has some issues with memory for blobs when constructing multiple objects (fix constant propagation pass to not treat capsules as the same object).
```py
torch.jit.script
def f(x):
    val = torch._C.Foo(5, 3)
    val2 = torch._C.Foo(100, 0)
    val.display()
    print(val.add(3))
```
- [ ] Can't define multiple constructors (need to define overload string. Currently not possible since we don't support overloaded methods).
- [x] `init` is a little bit different syntax than `pybind`. `.init<...>()` instead of `.def(py::init<>())`
- [x] I couldn't figure out how to add some files into the build so they'd be copied to the `include/` directories, so I symlinked them manually.
- [ ] Currently, the conversion from Python into Torchscript doesn't work.
- [ ] Torchbind also currently requires Python/Pybind dependency. Fixing this would probably involve some kind of macro to bind into Python when possible.
- [ ] We pass back into Python by value, currently. There's no way of passing by reference.
- [x] Currently can only register one method with the same type signature. This is because we create a `static auto opRegistry`, and the function is templated on the type signature.

Somewhat blocked on https://github.com/pytorch/pytorch/pull/21177. We currently use some structures that will be refactored by his PR (namely `return_type_to_ivalue` and `ivalue_to_arg_type`.
Pull Request resolved: https://github.com/pytorch/pytorch/pull/21098

Differential Revision: D16634872

Pulled By: Chillee

fbshipit-source-id: 1408bb89ea649c27d560df59e2cf9920467fe1de
2019-08-02 18:45:15 -07:00
..
api Support custom autograd functions in C++ (#23572) 2019-07-31 11:30:48 -07:00
autograd Allow empty Variables to be saved for backwards (#23618) 2019-07-31 19:51:35 -07:00
cuda Fix error message for a wrong fork CUDA (#23322) 2019-07-25 12:58:14 -07:00
distributed/c10d Enhance interpretation of GLOO_SOCKET_IFNAME (#22978) 2019-07-25 04:52:38 -07:00
generic pin_memory should not copy on already pinned tensors (#23484) 2019-07-30 21:16:23 -07:00
jit Initial torchbind prototype (#21098) 2019-08-02 18:45:15 -07:00
multiprocessing
nn
onnx
tensor Remove Type dispatch (#21964) 2019-06-30 04:11:35 -07:00
utils Rename AT_FORALL_SCALAR_TYPES_WITH_COMPLEX to AT_FORALL_SCALAR_TYPES_WITH_COMPLEX_AND_STUBS 2019-07-31 08:17:17 -07:00
byte_order.cpp Enabled BFloat16 storage (#21523) 2019-07-09 21:51:06 -07:00
byte_order.h Enabled BFloat16 storage (#21523) 2019-07-09 21:51:06 -07:00
copy_utils.h
CudaIPCTypes.cpp
CudaIPCTypes.h
DataLoader.cpp
DataLoader.h
Device.cpp
Device.h
dl.c
Dtype.cpp
Dtype.h allow passing Python built-in types as dtypes (#21215) 2019-06-06 13:17:23 -07:00
DynamicTypes.cpp Stop using Type in Python bindings (#21963) 2019-06-30 04:11:32 -07:00
DynamicTypes.h Remove Type dispatch (#21964) 2019-06-30 04:11:35 -07:00
Exceptions.cpp
Exceptions.h
Generator.cpp Remove many usages of Type (#21941) 2019-06-30 04:11:28 -07:00
Generator.h Refactor Random Number Generators in ATen (#21364) 2019-06-12 13:01:30 -07:00
Layout.cpp
Layout.h
MemoryFormat.cpp
MemoryFormat.h
Module.cpp Add torch._C._BUILD_NAMEDTENSOR() (#23623) 2019-08-02 11:37:25 -07:00
Module.h Refactor Random Number Generators in ATen (#21364) 2019-06-12 13:01:30 -07:00
PtrWrapper.cpp
PtrWrapper.h
python_dimname.cpp Implement named inference rule for torch.sum 2019-07-26 08:50:40 -07:00
python_dimname.h Implement named inference rule for torch.sum 2019-07-26 08:50:40 -07:00
python_headers.h
PythonTypes.h
QScheme.cpp Add qscheme() method (#20608) 2019-06-14 16:29:29 -07:00
QScheme.h Add qscheme() method (#20608) 2019-06-14 16:29:29 -07:00
README.md
serialization.cpp Enabled BFloat16 storage (#21523) 2019-07-09 21:51:06 -07:00
serialization.h Enabled BFloat16 storage (#21523) 2019-07-09 21:51:06 -07:00
Size.cpp serialize torch.Size object (#20952) 2019-06-25 10:44:35 -07:00
Size.h
Storage.cpp Enabled BFloat16 storage (#21523) 2019-07-09 21:51:06 -07:00
Storage.h Enabled BFloat16 storage (#21523) 2019-07-09 21:51:06 -07:00
StorageDefs.h
stub.cpp
THP_export.h Initial torchbind prototype (#21098) 2019-08-02 18:45:15 -07:00
THP.h
TypeInfo.cpp Add FakeQuantize Module (#21767) 2019-07-15 14:08:55 -07:00
TypeInfo.h
Types.h
utils.cpp Enabled BFloat16 storage (#21523) 2019-07-09 21:51:06 -07:00
utils.h Enabled BFloat16 storage (#21523) 2019-07-09 21:51:06 -07:00
WindowsTorchApiMacro.h

csrc

The csrc directory contains all of the code concerned with integration with Python. This is in contrast to lib, which contains the Torch libraries that are Python agnostic. csrc depends on lib, but not vice versa.

There are a number of utilities for easing integration with Python which are worth knowing about, which we briefly describe here. But the most important gotchas:

  • DO NOT forget to take out the GIL with AutoGil before calling Python API or bringing a THPObjectPtr into scope.

  • Make sure you include Python.h first in your header files, before any system headers; otherwise, you will get error: "_XOPEN_SOURCE" redefined error. If you pay attention to warnings, you will see where you need to do this.

Notes

Note [Storage is not nullptr]

Historically, Torch supported nullptr storage, as a minor optimization to avoid having to allocate a storage object when it would be empty. However, this is actually a confusing special case to deal with, so by-in-large, PyTorch assumes that, in fact, storage is never nullptr.

One important case where this assumption is important is when tracking the CUDA device a tensor is stored in: this information is stored solely in the storage, so if a storage is nullptr, we lose this information.

Although storage is never nullptr, the data field of THStorage may be nullptr. This mostly occurs when we want to pre-allocate an output tensor struct, but then have it be resized and filled with data by some operator: there's no point in allocating data for it in this case!

Files

Exceptions.h

Frequently when working with the Python API, you may call a function which returns an error. In this case, we want to return directly to the Python interpreter, so that this exception can be propagated accordingly; however, because the Python API is C-based, what actually will happen is it will return control to whatever C++ code called it. Similarly, if we raise a C++ exception, prior to returning to the Python interpreter, we must set the Python error flags, so it turns into a C++ exception.

Exceptions defines some useful helpers: HANDLE_TH_ERRORS, END_HANDLE_TH_ERRORS and an exception class python_error. You call them like this:

// Entry point from Python interpreter
PyObject* run() {
  HANDLE_TH_ERRORS
  ...
  if (!x) throw python_error();
  ...
  END_HANDLE_TH_ERRORS
}

The HANDLE_TH_ERRORS macro will catch all exceptions and convert them into an appropriate Python signal. python_error is a special exception which doesn't contain any info, instead it says, "An error occurred in the Python API; if you return to the interpreter, Python will raise that exception, nothing else needs to be done."

utils/auto_gil.h

Whenever you make any calls to the Python API, you must have taken out the Python GIL, as none of these calls are thread safe. AutoGIL is a RAII struct which handles taking and releasing the GIL. Use it like this:

void iWantToUsePython() {
  AutoGil gil;
  ...
}

In general, the compiler will NOT warn you if you use Python functionality without taking out the GIL, so DO NOT FORGET this call.

utils/object_ptr.h

THPPointer is a smart pointer class analogous to std::shared_ptr, but which is overloaded to handle reference counting scheme of various objects which are not based on shared_ptr. The most important overloads are:

  • PyObject (so important we've aliased it as THPObjectPtr), which hooks into Python reference counting. (By the way, that means you MUST take out the GIL before bringing one of these into scope!)

  • The various TH tensor and storage types (e.g., THTensor), which hook into TH's reference counting. (TH's reference counting IS thread safe, no locks necessary.)