Repository: pytorch/vision
Pull request: fix: use `inplace=None` as default in `ops.MLP`
If the default is `True`, then this casues an error during backprop that a tensor required for backpropagation was changed, if `dropout>0`.

Closes #7174 



Problem statement:
`dropout>0` in `ops.MLP` causes backward inplace error
### 🐛 Describe the bug

Since `inplace` is by default `True` in `ops.MLP`, this causes an error when backpropagating if `dropout>0`.

To reproduce: 
```python
import torch
from torchvision.ops import MLP

MLP(3, [3, 3], dropout=0.5, inplace=False)(torch.rand(3)).sum().backward()  # no error
MLP(3, [3, 3], dropout=0.5)(torch.rand(3)).sum().backward()  # causes an error
```

Here's the error:
```
Variable._execution_engine.run_backward(  # Calls into the C++ engine to run the backward pass
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.FloatTensor [3]], which is output 0 of ReluBackward0, is at version 4; expected version 3 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True).
```

Since the type hint for `inplace` is `Optional`, I would expect this not to happen (i.e. it is automatically turned off if `dropout>0`).

### Versions

```
PyTorch version: 1.13.0
Is debug build: False
CUDA used to build PyTorch: None
ROCM used to build PyTorch: N/A

OS: Manjaro Linux (x86_64)
GCC version: (GCC) 12.2.1 20230111
Clang version: 15.0.7
CMake version: version 3.25.2
Libc version: glibc-2.36

Python version: 3.9.13 | packaged by conda-forge | (main, May 27 2022, 16:58:50)  [GCC 10.3.0] (64-bit runtime)
Python platform: Linux-5.15.89-1-MANJARO-x86_64-with-glibc2.36
Is CUDA available: False
CUDA runtime version: No CUDA
CUDA_MODULE_LOADING set to: N/A
GPU models and configuration: No CUDA
Nvidia driver version: No CUDA
cuDNN version: No CUDA
HIP runtime version: N/A
MIOpen runtime version: N/A
Is XNNPACK available: True

CPU:
Architecture:                    x86_64
CPU op-mode(s):                  32-bit, 64-bit
Address sizes:                   48 bits physical, 48 bits virtual
Byte Order:                      Little Endian
CPU(s):                          16
On-line CPU(s) list:             0-15
Vendor ID:                       AuthenticAMD
Model name:                      AMD Ryzen 7 5825U with Radeon Graphics
CPU family:                      25
Model:                           80
Thread(s) per core:              2
Core(s) per socket:              8
Socket(s):                       1
Stepping:                        0
Frequency boost:                 enabled
CPU(s) scaling MHz:              50%
CPU max MHz:                     4546,8750
CPU min MHz:                     1600,0000
BogoMIPS:                        3994,77
Flags:                           fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf rapl pni pclmulqdq monitor ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs skinit wdt tce topoext perfctr_core perfctr_nb bpext perfctr_llc mwaitx cpb cat_l3 cdp_l3 hw_pstate ssbd mba ibrs ibpb stibp vmmcall fsgsbase bmi1 avx2 smep bmi2 erms invpcid cqm rdt_a rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local clzero irperf xsaveerptr rdpru wbnoinvd arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold avic v_vmsave_vmload vgif v_spec_ctrl umip pku ospke vaes vpclmulqdq rdpid overflow_recov succor smca fsrm
Virtualization:                  AMD-V
L1d cache:                       256 KiB (8 instances)
L1i cache:                       256 KiB (8 instances)
L2 cache:                        4 MiB (8 instances)
L3 cache:                        16 MiB (1 instance)
NUMA node(s):                    1
NUMA node0 CPU(s):               0-15
Vulnerability Itlb multihit:     Not affected
Vulnerability L1tf:              Not affected
Vulnerability Mds:               Not affected
Vulnerability Meltdown:          Not affected
Vulnerability Mmio stale data:   Not affected
Vulnerability Retbleed:          Not affected
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl and seccomp
Vulnerability Spectre v1:        Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2:        Mitigation; Retpolines, IBPB conditional, IBRS_FW, STIBP always-on, RSB filling, PBRSB-eIBRS Not affected
Vulnerability Srbds:             Not affected
Vulnerability Tsx async abort:   Not affected

Versions of relevant libraries:
[pip3] mypy-extensions==0.4.3
[pip3] numpy==1.23.4
[pip3] torch==1.13.0
[pip3] torchmetrics==0.11.0
[pip3] torchvision==0.14.0
[conda] blas                      2.116                       mkl    conda-forge
[conda] blas-devel                3.9.0            16_linux64_mkl    conda-forge
[conda] ffmpeg                    4.3                  hf484d3e_0    pytorch
[conda] libblas                   3.9.0            16_linux64_mkl    conda-forge
[conda] libcblas                  3.9.0            16_linux64_mkl    conda-forge
[conda] liblapack                 3.9.0            16_linux64_mkl    conda-forge
[conda] liblapacke                3.9.0            16_linux64_mkl    conda-forge
[conda] mkl                       2022.1.0           h84fe81f_915    conda-forge
[conda] mkl-devel                 2022.1.0           ha770c72_916    conda-forge
[conda] mkl-include               2022.1.0           h84fe81f_915    conda-forge
[conda] numpy                     1.23.4           py39h3d75532_1    conda-forge
[conda] pytorch                   1.13.0              py3.9_cpu_0    pytorch
[conda] pytorch-mutex             1.0                         cpu    pytorch
[conda] torchmetrics              0.11.0             pyhd8ed1ab_0    conda-forge
[conda] torchvision               0.14.0                 py39_cpu    pytorch
```

Hints from issue discussion:
Thanks for the report @nps1ngh, I can reproduce .

I'm not sure why we originally set the default to True when in practice we always pass `inplace=None` in our  transformers models (vit, swin, mvit - see original PR https://github.com/pytorch/vision/pull/6053/files). I'm tempted to treat this as a bug-fix and replace the default with `None` (which means "just use the same default as the layer, which usually is False").
This wouldn't be a change of result, so the worst that can happen is some slight perf downgrade. WDYT @vfdev-5 @pmeier ?

Side note @nps1ngh :

> Since the type hint for inplace is Optional, I would expect this not to happen (i.e. it is automatically turned off if dropout>0).

The `Optional` part in the type hint only indicates that `None` is an accepted value - it doesn't say anything regarding the semantics of a parameter. It also doesn't say anything about the default value of a parameter (or whether it has one).

Anyway, **do not trust the type annotations of torchvision**.  A lot of them are wrong, mostly because we have to please torchscript. Rely on the docstring instead to figure out what types are accepted.
+1 for treating this as bug fix.
Yes, seems like `inplace` parameter was introduced only in torchvision and is absent in other examples ilke multimodal, DETR, timm etc. I agree to handle this as a bug and set default to None

Commit message: add `optional` to *documentation* type hint for `inplace` in `ops.MLP`

Patch to review:
diff --git a/torchvision/ops/misc.py b/torchvision/ops/misc.py
index 91784e6028f..72a3faeae95 100644
--- a/torchvision/ops/misc.py
+++ b/torchvision/ops/misc.py
@@ -268,7 +268,7 @@ class MLP(torch.nn.Sequential):
         hidden_channels (List[int]): List of the hidden channel dimensions
         norm_layer (Callable[..., torch.nn.Module], optional): Norm layer that will be stacked on top of the linear layer. If ``None`` this layer won't be used. Default: ``None``
         activation_layer (Callable[..., torch.nn.Module], optional): Activation function which will be stacked on top of the normalization layer (if not None), otherwise on top of the linear layer. If ``None`` this layer won't be used. Default: ``torch.nn.ReLU``
-        inplace (bool): Parameter for the activation layer, which can optionally do the operation in-place. Default ``True``
+        inplace (bool, optional): Parameter for the activation layer, which can optionally do the operation in-place. Default ``None``
         bias (bool): Whether to use bias in the linear layer. Default ``True``
         dropout (float): The probability for the dropout layer. Default: 0.0
     """
@@ -279,7 +279,7 @@ def __init__(
         hidden_channels: List[int],
         norm_layer: Optional[Callable[..., torch.nn.Module]] = None,
         activation_layer: Optional[Callable[..., torch.nn.Module]] = torch.nn.ReLU,
-        inplace: Optional[bool] = True,
+        inplace: Optional[bool] = None,
         bias: bool = True,
         dropout: float = 0.0,
     ):


Code review comments:
diff_hunk: @@ -268,7 +268,7 @@ class MLP(torch.nn.Sequential):
         hidden_channels (List[int]): List of the hidden channel dimensions
         norm_layer (Callable[..., torch.nn.Module], optional): Norm layer that will be stacked on top of the linear layer. If ``None`` this layer won't be used. Default: ``None``
         activation_layer (Callable[..., torch.nn.Module], optional): Activation function which will be stacked on top of the normalization layer (if not None), otherwise on top of the linear layer. If ``None`` this layer won't be used. Default: ``torch.nn.ReLU``
-        inplace (bool): Parameter for the activation layer, which can optionally do the operation in-place. Default ``True``
+        inplace (bool, optional): Parameter for the activation layer, which can optionally do the operation in-place. Default ``None``
path: torchvision/ops/misc.py
text: @user1:
```suggestion
        inplace (bool, optional): Parameter for the activation layer, which can optionally do the operation in-place.
            Default is ``None``, which uses the respective default values of the ``activation_layer`` and Dropout layer.
```