1*da0073e9SAndroid Build Coastguard WorkerThis directory contains the low-level tensor libraries for PyTorch, 2*da0073e9SAndroid Build Coastguard Workeras well as the new ATen C++ bindings. 3*da0073e9SAndroid Build Coastguard Worker 4*da0073e9SAndroid Build Coastguard WorkerThe low-level libraries trace their lineage from the original Torch. There are 5*da0073e9SAndroid Build Coastguard Workermultiple variants of the library, summarized here: 6*da0073e9SAndroid Build Coastguard Worker 7*da0073e9SAndroid Build Coastguard Worker* TH = TorcH 8*da0073e9SAndroid Build Coastguard Worker* THC = TorcH Cuda 9*da0073e9SAndroid Build Coastguard Worker* THCS = TorcH Cuda Sparse (now defunct) 10*da0073e9SAndroid Build Coastguard Worker* THNN = TorcH Neural Network (now defunct) 11*da0073e9SAndroid Build Coastguard Worker* THS = TorcH Sparse (now defunct) 12*da0073e9SAndroid Build Coastguard Worker 13*da0073e9SAndroid Build Coastguard Worker(You'll also see these abbreviations show up in symbol names.) 14*da0073e9SAndroid Build Coastguard Worker 15*da0073e9SAndroid Build Coastguard Worker## Reference counting 16*da0073e9SAndroid Build Coastguard Worker 17*da0073e9SAndroid Build Coastguard WorkerPyTorch employs reference counting in order to permit tensors to provide 18*da0073e9SAndroid Build Coastguard Workerdiffering views on a common underlying storage. For example, when you call 19*da0073e9SAndroid Build Coastguard Workerview() on a Tensor, a new THTensor is allocated with differing dimensions, 20*da0073e9SAndroid Build Coastguard Workerbut it shares the same c10::StorageImpl with the original tensor. 21*da0073e9SAndroid Build Coastguard Worker 22*da0073e9SAndroid Build Coastguard WorkerUnfortunately, this means we are in the business of manually tracking reference 23*da0073e9SAndroid Build Coastguard Workercounts inside our C library code. Fortunately, for most of our library code implementing 24*da0073e9SAndroid Build Coastguard Workertensor operations, there is only one rule you have to remember: 25*da0073e9SAndroid Build Coastguard Worker 26*da0073e9SAndroid Build Coastguard Worker> **Golden Rule of Reference Counting:** You must either FREE or RETURN 27*da0073e9SAndroid Build Coastguard Worker> a pointer which was returned by a function whose name begins with 28*da0073e9SAndroid Build Coastguard Worker> `new` or which you called `retain` on. 29*da0073e9SAndroid Build Coastguard Worker> If you return this pointer, your function name must begin with `new`. 30*da0073e9SAndroid Build Coastguard Worker 31*da0073e9SAndroid Build Coastguard WorkerIn a long function, there may be many invocations of functions with `new` in 32*da0073e9SAndroid Build Coastguard Workertheir name. Your responsibility is to go through each of them and ensure 33*da0073e9SAndroid Build Coastguard Workerthat there is a matching `free` for it for EACH exit point of the function. 34*da0073e9SAndroid Build Coastguard Worker 35*da0073e9SAndroid Build Coastguard Worker### Examples 36*da0073e9SAndroid Build Coastguard Worker 37*da0073e9SAndroid Build Coastguard WorkerSuppose you want to get a reference to the indices of a sparse tensor. This 38*da0073e9SAndroid Build Coastguard Workerfunction is called `newIndices`. The `new` means you MUST free it when you're 39*da0073e9SAndroid Build Coastguard Workerdone (usually at the end of your function.) (It's worth noting that 40*da0073e9SAndroid Build Coastguard Worker`newIndices` doesn't actually allocate a fresh indices tensor; it just gives 41*da0073e9SAndroid Build Coastguard Workeryou a pointer to the existing one.) DO NOT directly access the member 42*da0073e9SAndroid Build Coastguard Workervariables of the struct. 43*da0073e9SAndroid Build Coastguard Worker 44*da0073e9SAndroid Build Coastguard Worker``` 45*da0073e9SAndroid Build Coastguard WorkerTHIndexTensor *indices = THSTensor_(newIndices)(state, sparse); 46*da0073e9SAndroid Build Coastguard Worker// ... do some stuff ... 47*da0073e9SAndroid Build Coastguard WorkerTHIndexTensor_(free)(state, indices); 48*da0073e9SAndroid Build Coastguard Worker``` 49*da0073e9SAndroid Build Coastguard Worker 50*da0073e9SAndroid Build Coastguard WorkerLet's take a look at the implementation of `newIndices`. This doesn't free the 51*da0073e9SAndroid Build Coastguard Workerreturn result of `newNarrow`, but returns it. This justifies the `new` in its 52*da0073e9SAndroid Build Coastguard Workername. 53*da0073e9SAndroid Build Coastguard Worker 54*da0073e9SAndroid Build Coastguard Worker``` 55*da0073e9SAndroid Build Coastguard WorkerTHIndexTensor *THSTensor_(newIndices)(const THSTensor *self) { 56*da0073e9SAndroid Build Coastguard Worker // ... 57*da0073e9SAndroid Build Coastguard Worker return THIndexTensor_(newNarrow)(self->indices, 1, 0, self->nnz); 58*da0073e9SAndroid Build Coastguard Worker} 59*da0073e9SAndroid Build Coastguard Worker``` 60*da0073e9SAndroid Build Coastguard Worker 61*da0073e9SAndroid Build Coastguard WorkerPassing an object to another function does NOT absolve you of responsibility 62*da0073e9SAndroid Build Coastguard Workerof freeing it. If that function holds on to a pointer to the object, it 63*da0073e9SAndroid Build Coastguard Workerwill `retain` it itself. 64*da0073e9SAndroid Build Coastguard Worker 65*da0073e9SAndroid Build Coastguard Worker``` 66*da0073e9SAndroid Build Coastguard Worker THByteStorage *inferred_size = THByteStorage_newInferSize(size, numel); 67*da0073e9SAndroid Build Coastguard Worker THTensor_(setStorage)(self, tensor->storage, tensor->storageOffset, inferred_size, NULL); 68*da0073e9SAndroid Build Coastguard Worker c10::raw::intrusive_ptr::decref(inferred_size); 69*da0073e9SAndroid Build Coastguard Worker``` 70*da0073e9SAndroid Build Coastguard Worker 71*da0073e9SAndroid Build Coastguard WorkerSometimes, you have a tensor in hand which you'd like to use directly, but 72*da0073e9SAndroid Build Coastguard Workerunder some conditions you have to call, e.g., `newContiguous`, to get it into 73*da0073e9SAndroid Build Coastguard Workerthe correct form: 74*da0073e9SAndroid Build Coastguard Worker 75*da0073e9SAndroid Build Coastguard Worker``` 76*da0073e9SAndroid Build Coastguard Worker if (!(k_->stride(3) == 1) || !(k_->stride[2] == k_->size(3))) { 77*da0073e9SAndroid Build Coastguard Worker kernel = THTensor_(newContiguous)(k_); 78*da0073e9SAndroid Build Coastguard Worker } else { 79*da0073e9SAndroid Build Coastguard Worker THTensor_(retain)(k_); 80*da0073e9SAndroid Build Coastguard Worker kernel = k_; 81*da0073e9SAndroid Build Coastguard Worker } 82*da0073e9SAndroid Build Coastguard Worker ... 83*da0073e9SAndroid Build Coastguard Worker c10::raw::intrusive_ptr::decref(kernel); 84*da0073e9SAndroid Build Coastguard Worker``` 85*da0073e9SAndroid Build Coastguard Worker 86*da0073e9SAndroid Build Coastguard WorkerIn this case, we have (redundantly) called `retain` on `k_`, so that we can 87*da0073e9SAndroid Build Coastguard Workerunconditionally free `kernel` at the end of the function; intuitively, you 88*da0073e9SAndroid Build Coastguard Workerwant it to be possible to replace the conditional expression with an equivalent 89*da0073e9SAndroid Build Coastguard Workerfunction call, e.g., `kernel = THTensor_(newContiguous2D)(k_)`. 90*da0073e9SAndroid Build Coastguard Worker 91*da0073e9SAndroid Build Coastguard Worker### Tips 92*da0073e9SAndroid Build Coastguard Worker 93*da0073e9SAndroid Build Coastguard Worker* If you have an early exit in a function (via a `return`), don't forget to 94*da0073e9SAndroid Build Coastguard Worker `free` any pointers which you allocated up to this point. If at all possible, 95*da0073e9SAndroid Build Coastguard Worker move early exits prior to these allocations, so that you don't have to clean up. 96*da0073e9SAndroid Build Coastguard Worker 97*da0073e9SAndroid Build Coastguard Worker* Very occasionally, you may be able to implement an algorithm more efficiently 98*da0073e9SAndroid Build Coastguard Worker if you "destroy" its input. This is a `move`; after moving an object away, 99*da0073e9SAndroid Build Coastguard Worker you must NOT `free` it. This is the one exception to the rule, and at the 100*da0073e9SAndroid Build Coastguard Worker moment there is only one instance of `move` in the code base. 101*da0073e9SAndroid Build Coastguard Worker 102*da0073e9SAndroid Build Coastguard Worker* We use `THError` to signal error cases, and fortunately, 103*da0073e9SAndroid Build Coastguard Worker you do NOT need to make sure you've freed everything before calling `THError`, 104*da0073e9SAndroid Build Coastguard Worker because by default, it aborts the entire process. However, it's good style 105*da0073e9SAndroid Build Coastguard Worker to call `THError` before performing any allocations, since in some cases we 106*da0073e9SAndroid Build Coastguard Worker sketchily throw a C++ exception and try to recover (in particular, the test 107*da0073e9SAndroid Build Coastguard Worker suite does this.) 108