├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── MANIFEST.in
├── Makefile
├── MinkowskiEngine
├── MinkowskiBroadcast.py
├── MinkowskiChannelwiseConvolution.py
├── MinkowskiCommon.py
├── MinkowskiConvolution.py
├── MinkowskiCoordinateManager.py
├── MinkowskiFunctional.py
├── MinkowskiInterpolation.py
├── MinkowskiKernelGenerator.py
├── MinkowskiNetwork.py
├── MinkowskiNonlinearity.py
├── MinkowskiNormalization.py
├── MinkowskiOps.py
├── MinkowskiPooling.py
├── MinkowskiPruning.py
├── MinkowskiSparseTensor.py
├── MinkowskiTensor.py
├── MinkowskiTensorField.py
├── MinkowskiUnion.py
├── __init__.py
├── diagnostics.py
├── modules
│ ├── __init__.py
│ ├── resnet_block.py
│ └── senet_block.py
├── sparse_matrix_functions.py
└── utils
│ ├── __init__.py
│ ├── collation.py
│ ├── coords.py
│ ├── gradcheck.py
│ ├── init.py
│ ├── quantization.py
│ └── summary.py
├── README.md
├── docker
└── Dockerfile
├── docs
├── .gitignore
├── Makefile
├── README.md
├── _templates
│ └── layout.html
├── benchmark.md
├── broadcast.rst
├── common.rst
├── conf.py
├── convolution.rst
├── coords.rst
├── demo
│ ├── interop.rst
│ ├── modelnet40_classification.rst
│ ├── multigpu.md
│ ├── pointnet.md
│ ├── segmentation.rst
│ ├── sparse_tensor_reconstruction.rst
│ └── training.rst
├── guides.md
├── images
│ ├── classification_3d_net.png
│ ├── conv_dense.gif
│ ├── conv_generalized.gif
│ ├── conv_sparse.gif
│ ├── conv_sparse_conv.gif
│ ├── demo_reconstruction.png
│ ├── detection_3d_net.png
│ ├── generative_3d_net.png
│ ├── generative_3d_results.gif
│ ├── kernel_map.gif
│ ├── segmentation.png
│ └── segmentation_3d_net.png
├── index.rst
├── interp.rst
├── issues.md
├── migration_05.md
├── misc.rst
├── nonlinearity.rst
├── normalization.rst
├── pooling.rst
├── pruning.rst
├── quick_start.md
├── sparse_tensor.rst
├── sparse_tensor_network.rst
├── terminology.rst
├── tutorial
│ ├── convolution_basic.rst
│ └── sparse_tensor_basic.rst
├── union.rst
└── utils.rst
├── examples
├── README.md
├── __init__.py
├── classification_modelnet40.py
├── common.py
├── completion.py
├── convolution.py
├── download_modelnet40.sh
├── example.py
├── indoor.py
├── minkunet.py
├── multigpu.py
├── multigpu_ddp.py
├── multigpu_lightning.py
├── pointnet.py
├── reconstruction.py
├── resnet.py
├── sparse_tensor_basic.py
├── stack_unet.py
├── training.py
├── unet.py
└── vae.py
├── pybind
├── extern.hpp
├── minkowski.cpp
└── minkowski.cu
├── requirements.txt
├── setup.py
├── src
├── 3rdparty
│ ├── concurrent_unordered_map.cuh
│ ├── cudf
│ │ ├── detail
│ │ │ ├── nvtx
│ │ │ │ ├── nvtx3.hpp
│ │ │ │ └── ranges.hpp
│ │ │ └── utilities
│ │ │ │ ├── device_atomics.cuh
│ │ │ │ ├── device_operators.cuh
│ │ │ │ └── hash_functions.cuh
│ │ ├── types.h
│ │ ├── types.hpp
│ │ └── utilities
│ │ │ ├── error.hpp
│ │ │ └── legacy
│ │ │ └── wrapper_types.hpp
│ ├── hash
│ │ ├── hash_allocator.cuh
│ │ ├── helper_functions.cuh
│ │ └── managed.cuh
│ └── robin_hood.h
├── allocators.cuh
├── broadcast_cpu.cpp
├── broadcast_gpu.cu
├── broadcast_kernel.cu
├── broadcast_kernel.cuh
├── broadcast_kernel.hpp
├── common.hpp
├── convolution_cpu.cpp
├── convolution_gpu.cu
├── convolution_kernel.cu
├── convolution_kernel.cuh
├── convolution_kernel.hpp
├── convolution_transpose_cpu.cpp
├── convolution_transpose_gpu.cu
├── coordinate.hpp
├── coordinate_map.hpp
├── coordinate_map_cpu.hpp
├── coordinate_map_functors.cuh
├── coordinate_map_gpu.cu
├── coordinate_map_gpu.cuh
├── coordinate_map_key.hpp
├── coordinate_map_manager.cpp
├── coordinate_map_manager.cu
├── coordinate_map_manager.hpp
├── direct_max_pool.cpp
├── dispatcher.hpp
├── errors.hpp
├── global_pooling_cpu.cpp
├── global_pooling_gpu.cu
├── gpu.cu
├── gpu.cuh
├── interpolation_cpu.cpp
├── interpolation_gpu.cu
├── interpolation_kernel.hpp
├── kernel_map.cuh
├── kernel_map.hpp
├── kernel_region.hpp
├── local_pooling_cpu.cpp
├── local_pooling_gpu.cu
├── local_pooling_transpose_cpu.cpp
├── local_pooling_transpose_gpu.cu
├── math_functions.cuh
├── math_functions.hpp
├── math_functions_cpu.cpp
├── math_functions_gpu.cu
├── mkl_alternate.hpp
├── pooling_avg_kernel.cu
├── pooling_avg_kernel.cuh
├── pooling_avg_kernel.hpp
├── pooling_max_kernel.cu
├── pooling_max_kernel.cuh
├── pooling_max_kernel.hpp
├── primitives
│ └── small_vector.hpp
├── pruning.hpp
├── pruning_cpu.cpp
├── pruning_gpu.cu
├── quantization.cpp
├── sharedmem.cuh
├── spmm.cu
├── spmm.cuh
├── storage.cuh
├── types.hpp
└── utils.hpp
└── tests
├── cpp
├── README.md
├── __init__.py
├── convolution_cpu.py
├── convolution_cpu_test.py
├── convolution_gpu_test.py
├── convolution_test.cpp
├── convolution_test.cu
├── coordinate_map_cpu_test.cpp
├── coordinate_map_cpu_test.py
├── coordinate_map_gpu_test.cu
├── coordinate_map_gpu_test.py
├── coordinate_map_key_test.cpp
├── coordinate_map_key_test.py
├── coordinate_map_manager_cpu_test.cpp
├── coordinate_map_manager_cpu_test.py
├── coordinate_map_manager_gpu_test.cu
├── coordinate_map_manager_gpu_test.py
├── coordinate_test.cpp
├── coordinate_test.py
├── kernel_region_cpu_test.cpp
├── kernel_region_cpu_test.py
├── kernel_region_gpu_test.cu
├── kernel_region_gpu_test.py
├── setup.py
├── test_all.sh
├── type_test.cpp
├── type_test.py
└── utils.py
├── python
├── __init__.py
├── broadcast.py
├── chwise_conv.py
├── common.py
├── conv_on_coords.py
├── convolution.py
├── coordinate_manager.py
├── dense.py
├── direct_pool.py
├── global.py
├── interpolation.py
├── kernel_map.py
├── network_speed.py
├── norm.py
├── pool.py
├── pruning.py
├── quantization.py
├── sparse_tensor.py
├── spmm.py
├── stack.py
├── strided_conv.py
├── summary.py
├── tensor_field.py
├── union.py
└── utility_functions.py
└── run_test.py
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | - Please complete all sections of this template if applicable. For installation, you must report the environment. Otherwise, your issue will be closed automatically.
14 |
15 |
16 |
17 | ************************************************************************************
18 | **To Reproduce**
19 | Steps to reproduce the behavior. If the code is not attached and cannot be reproduced easily, the bug report will be closed without any comments.
20 |
21 | - a minimally reproducible code.
22 |
23 |
24 |
25 | ************************************************************************************
26 | **Expected behavior**
27 | A clear and concise description of what you expected to happen.
28 |
29 |
30 |
31 | ************************************************************************************
32 | **Desktop (please complete the following information):**
33 |
34 | - OS: [e.g. Ubuntu 18.04]
35 | - Python version: [e.g. 3.8.5]
36 | - Pytorch version: [e.g. 1.7.1]
37 | - CUDA version: [e.g. 11.1]
38 | - NVIDIA Driver version: [e.g. 450.11]
39 | - Minkowski Engine version [e.g. 0.5.0]
40 | - Output of the following command. (If you installed the latest MinkowskiEngine, paste the output of `python -c "import MinkowskiEngine as ME; ME.print_diagnostics()"`. Otherwise, paste the output of the following command.)
41 |
42 | ```
43 | wget -q https://raw.githubusercontent.com/NVIDIA/MinkowskiEngine/master/MinkowskiEngine/diagnostics.py ; python diagnostics.py
44 | ```
45 |
46 |
47 | ************************************************************************************
48 | **Additional context**
49 | Add any other context about the problem here.
50 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.so
2 | *.[o,d,a]
3 | *.swo
4 | *.swp
5 | *.swn
6 | *.pyc
7 |
8 | build/
9 | objs/
10 | dist/
11 | MinkowskiEngine.egg-info/
12 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 NVIDIA CORPORATION.
4 | Copyright (c) 2018-2020 Chris Choy (chrischoy@ai.stanford.edu)
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | this software and associated documentation files (the "Software"), to deal in
8 | the Software without restriction, including without limitation the rights to
9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10 | of the Software, and to permit persons to whom the Software is furnished to do
11 | so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
24 | Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
25 | Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
26 | of the code.
27 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include Makefile
2 | recursive-include src *.hpp *.cpp *.cu *.cuh *.h
3 | recursive-include pybind *.hpp *.cpp
4 |
--------------------------------------------------------------------------------
/MinkowskiEngine/MinkowskiCommon.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2020 NVIDIA CORPORATION.
2 | # Copyright (c) 2018-2020 Chris Choy (chrischoy@ai.stanford.edu).
3 | #
4 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
5 | # this software and associated documentation files (the "Software"), to deal in
6 | # the Software without restriction, including without limitation the rights to
7 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8 | # of the Software, and to permit persons to whom the Software is furnished to do
9 | # so, subject to the following conditions:
10 | #
11 | # The above copyright notice and this permission notice shall be included in all
12 | # copies or substantial portions of the Software.
13 | #
14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | # SOFTWARE.
21 | #
22 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
23 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
24 | # of the code.
25 | from collections.abc import Sequence
26 | import numpy as np
27 | from typing import Union
28 |
29 | import torch
30 |
31 | from torch.nn import Module
32 |
33 | import MinkowskiEngineBackend._C as MEB
34 |
35 |
36 | StrideType = Union[int, Sequence, np.ndarray, torch.IntTensor]
37 |
38 |
39 | def convert_to_int_list(
40 | arg: Union[int, Sequence, np.ndarray, torch.Tensor], dimension: int
41 | ):
42 | if isinstance(arg, list):
43 | assert len(arg) == dimension
44 | return arg
45 |
46 | if isinstance(arg, (Sequence, np.ndarray, torch.Tensor)):
47 | tmp = [i for i in arg]
48 | assert len(tmp) == dimension
49 | elif np.isscalar(arg): # Assume that it is a scalar
50 | tmp = [int(arg) for i in range(dimension)]
51 | else:
52 | raise ValueError("Input must be a scalar or a sequence")
53 |
54 | return tmp
55 |
56 |
57 | def convert_to_int_tensor(
58 | arg: Union[int, Sequence, np.ndarray, torch.IntTensor], dimension: int
59 | ):
60 | if isinstance(arg, torch.IntTensor):
61 | assert arg.numel() == dimension
62 | return arg
63 |
64 | if isinstance(arg, (Sequence, np.ndarray)):
65 | tmp = torch.IntTensor([i for i in arg])
66 | assert tmp.numel() == dimension
67 | elif np.isscalar(arg): # Assume that it is a scalar
68 | tmp = torch.IntTensor([int(arg) for i in range(dimension)])
69 | else:
70 | raise ValueError("Input must be a scalar or a sequence")
71 |
72 | return tmp
73 |
74 |
75 | def prep_args(
76 | tensor_stride: Union[int, Sequence, np.ndarray, torch.IntTensor],
77 | stride: Union[int, Sequence, np.ndarray, torch.IntTensor],
78 | kernel_size: Union[int, Sequence, np.ndarray, torch.IntTensor],
79 | dilation: Union[int, Sequence, np.ndarray, torch.IntTensor],
80 | region_type: Union[int, MEB.RegionType],
81 | D=-1,
82 | ):
83 | assert torch.prod(
84 | kernel_size > 0
85 | ), f"kernel_size must be a positive integer, provided {kernel_size}"
86 | assert D > 0, f"dimension must be a positive integer, {D}"
87 | tensor_stride = convert_to_int_tensor(tensor_stride, D)
88 | stride = convert_to_int_tensor(stride, D)
89 | kernel_size = convert_to_int_tensor(kernel_size, D)
90 | dilation = convert_to_int_tensor(dilation, D)
91 | region_type = int(region_type)
92 | return (
93 | tensor_stride,
94 | stride,
95 | kernel_size,
96 | dilation,
97 | region_type,
98 | )
99 |
100 |
101 | def get_postfix(tensor: torch.Tensor):
102 | postfix = "GPU" if tensor.is_cuda else "CPU"
103 | return postfix
104 |
105 |
106 | class MinkowskiModuleBase(Module):
107 | pass
108 |
109 |
110 | def get_minkowski_function(name, variable):
111 | fn_name = name + get_postfix(variable)
112 | if hasattr(MEB, fn_name):
113 | return getattr(MEB, fn_name)
114 | else:
115 | if variable.is_cuda:
116 | raise ValueError(
117 | f"Function {fn_name} not available. Please compile MinkowskiEngine with `torch.cuda.is_available()` is `True`."
118 | )
119 | else:
120 | raise ValueError(f"Function {fn_name} not available.")
121 |
--------------------------------------------------------------------------------
/MinkowskiEngine/MinkowskiNetwork.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | # this software and associated documentation files (the "Software"), to deal in
5 | # the Software without restriction, including without limitation the rights to
6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | # of the Software, and to permit persons to whom the Software is furnished to do
8 | # so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in all
11 | # copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 | #
21 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | # of the code.
24 | from abc import ABC, abstractmethod
25 |
26 | import torch.nn as nn
27 |
28 | from MinkowskiSparseTensor import SparseTensor
29 |
30 |
31 | class MinkowskiNetwork(nn.Module, ABC):
32 | """
33 | MinkowskiNetwork: an abstract class for sparse convnets.
34 |
35 | Note: All modules that use the same coordinates must use the same net_metadata
36 | """
37 |
38 | def __init__(self, D):
39 | super(MinkowskiNetwork, self).__init__()
40 | self.D = D
41 |
42 | @abstractmethod
43 | def forward(self, x):
44 | pass
45 |
46 | def init(self, x):
47 | """
48 | Initialize coordinates if it does not exist
49 | """
50 | nrows = self.get_nrows(1)
51 | if nrows < 0:
52 | if isinstance(x, SparseTensor):
53 | self.initialize_coords(x.coords_man)
54 | else:
55 | raise ValueError('Initialize input coordinates')
56 | elif nrows != x.F.size(0):
57 | raise ValueError('Input size does not match the coordinate size')
58 |
--------------------------------------------------------------------------------
/MinkowskiEngine/diagnostics.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import os
3 | import platform
4 | import subprocess
5 |
6 |
7 | def parse_nvidia_smi():
8 | sp = subprocess.Popen(
9 | ["nvidia-smi", "-q"], stdout=subprocess.PIPE, stderr=subprocess.PIPE
10 | )
11 | out_dict = dict()
12 | for item in sp.communicate()[0].decode("utf-8").split("\n"):
13 | if item.count(":") == 1:
14 | key, val = [i.strip() for i in item.split(":")]
15 | out_dict[key] = val
16 | return out_dict
17 |
18 |
19 | def print_diagnostics():
20 | print("==========System==========")
21 | print(platform.platform())
22 | os.system("cat /etc/lsb-release")
23 | print(sys.version)
24 |
25 | print("==========Pytorch==========")
26 | try:
27 | import torch
28 |
29 | print(torch.__version__)
30 | print(f"torch.cuda.is_available(): {torch.cuda.is_available()}")
31 | except ImportError:
32 | print("torch not installed")
33 |
34 | print("==========NVIDIA-SMI==========")
35 | os.system("which nvidia-smi")
36 | for k, v in parse_nvidia_smi().items():
37 | if "version" in k.lower():
38 | print(k, v)
39 |
40 | print("==========NVCC==========")
41 | os.system("which nvcc")
42 | os.system("nvcc --version")
43 |
44 | print("==========CC==========")
45 | CC = "c++"
46 | if "CC" in os.environ or "CXX" in os.environ:
47 | # distutils only checks CC not CXX
48 | if "CXX" in os.environ:
49 | os.environ["CC"] = os.environ["CXX"]
50 | CC = os.environ["CXX"]
51 | else:
52 | CC = os.environ["CC"]
53 | print(f"CC={CC}")
54 | os.system(f"which {CC}")
55 | os.system(f"{CC} --version")
56 |
57 | print("==========MinkowskiEngine==========")
58 | try:
59 | import MinkowskiEngine as ME
60 |
61 | print(ME.__version__)
62 | print(f"MinkowskiEngine compiled with CUDA Support: {ME.is_cuda_available()}")
63 | print(f"NVCC version MinkowskiEngine is compiled: {ME.cuda_version()}")
64 | print(f"CUDART version MinkowskiEngine is compiled: {ME.cudart_version()}")
65 | except ImportError:
66 | print("MinkowskiEngine not installed")
67 |
68 |
69 | if __name__ == "__main__":
70 | print_diagnostics()
71 |
--------------------------------------------------------------------------------
/MinkowskiEngine/modules/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | # this software and associated documentation files (the "Software"), to deal in
5 | # the Software without restriction, including without limitation the rights to
6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | # of the Software, and to permit persons to whom the Software is furnished to do
8 | # so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in all
11 | # copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 | #
21 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | # of the code.
24 |
--------------------------------------------------------------------------------
/MinkowskiEngine/modules/resnet_block.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | # this software and associated documentation files (the "Software"), to deal in
5 | # the Software without restriction, including without limitation the rights to
6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | # of the Software, and to permit persons to whom the Software is furnished to do
8 | # so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in all
11 | # copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 | #
21 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | # of the code.
24 | import torch.nn as nn
25 |
26 | import MinkowskiEngine as ME
27 |
28 |
29 | class BasicBlock(nn.Module):
30 | expansion = 1
31 |
32 | def __init__(self,
33 | inplanes,
34 | planes,
35 | stride=1,
36 | dilation=1,
37 | downsample=None,
38 | bn_momentum=0.1,
39 | dimension=-1):
40 | super(BasicBlock, self).__init__()
41 | assert dimension > 0
42 |
43 | self.conv1 = ME.MinkowskiConvolution(
44 | inplanes, planes, kernel_size=3, stride=stride, dilation=dilation, dimension=dimension)
45 | self.norm1 = ME.MinkowskiBatchNorm(planes, momentum=bn_momentum)
46 | self.conv2 = ME.MinkowskiConvolution(
47 | planes, planes, kernel_size=3, stride=1, dilation=dilation, dimension=dimension)
48 | self.norm2 = ME.MinkowskiBatchNorm(planes, momentum=bn_momentum)
49 | self.relu = ME.MinkowskiReLU(inplace=True)
50 | self.downsample = downsample
51 |
52 | def forward(self, x):
53 | residual = x
54 |
55 | out = self.conv1(x)
56 | out = self.norm1(out)
57 | out = self.relu(out)
58 |
59 | out = self.conv2(out)
60 | out = self.norm2(out)
61 |
62 | if self.downsample is not None:
63 | residual = self.downsample(x)
64 |
65 | out += residual
66 | out = self.relu(out)
67 |
68 | return out
69 |
70 |
71 | class Bottleneck(nn.Module):
72 | expansion = 4
73 |
74 | def __init__(self,
75 | inplanes,
76 | planes,
77 | stride=1,
78 | dilation=1,
79 | downsample=None,
80 | bn_momentum=0.1,
81 | dimension=-1):
82 | super(Bottleneck, self).__init__()
83 | assert dimension > 0
84 |
85 | self.conv1 = ME.MinkowskiConvolution(
86 | inplanes, planes, kernel_size=1, dimension=dimension)
87 | self.norm1 = ME.MinkowskiBatchNorm(planes, momentum=bn_momentum)
88 |
89 | self.conv2 = ME.MinkowskiConvolution(
90 | planes, planes, kernel_size=3, stride=stride, dilation=dilation, dimension=dimension)
91 | self.norm2 = ME.MinkowskiBatchNorm(planes, momentum=bn_momentum)
92 |
93 | self.conv3 = ME.MinkowskiConvolution(
94 | planes, planes * self.expansion, kernel_size=1, dimension=dimension)
95 | self.norm3 = ME.MinkowskiBatchNorm(
96 | planes * self.expansion, momentum=bn_momentum)
97 |
98 | self.relu = ME.MinkowskiReLU(inplace=True)
99 | self.downsample = downsample
100 |
101 | def forward(self, x):
102 | residual = x
103 |
104 | out = self.conv1(x)
105 | out = self.norm1(out)
106 | out = self.relu(out)
107 |
108 | out = self.conv2(out)
109 | out = self.norm2(out)
110 | out = self.relu(out)
111 |
112 | out = self.conv3(out)
113 | out = self.norm3(out)
114 |
115 | if self.downsample is not None:
116 | residual = self.downsample(x)
117 |
118 | out += residual
119 | out = self.relu(out)
120 |
121 | return out
122 |
--------------------------------------------------------------------------------
/MinkowskiEngine/modules/senet_block.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | # this software and associated documentation files (the "Software"), to deal in
5 | # the Software without restriction, including without limitation the rights to
6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | # of the Software, and to permit persons to whom the Software is furnished to do
8 | # so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in all
11 | # copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 | #
21 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | # of the code.
24 | import torch.nn as nn
25 |
26 | import MinkowskiEngine as ME
27 |
28 | from MinkowskiEngine.modules.resnet_block import BasicBlock, Bottleneck
29 |
30 |
31 | class SELayer(nn.Module):
32 |
33 | def __init__(self, channel, reduction=16, D=-1):
34 | # Global coords does not require coords_key
35 | super(SELayer, self).__init__()
36 | self.fc = nn.Sequential(
37 | ME.MinkowskiLinear(channel, channel // reduction),
38 | ME.MinkowskiReLU(inplace=True),
39 | ME.MinkowskiLinear(channel // reduction, channel),
40 | ME.MinkowskiSigmoid())
41 | self.pooling = ME.MinkowskiGlobalPooling()
42 | self.broadcast_mul = ME.MinkowskiBroadcastMultiplication()
43 |
44 | def forward(self, x):
45 | y = self.pooling(x)
46 | y = self.fc(y)
47 | return self.broadcast_mul(x, y)
48 |
49 |
50 | class SEBasicBlock(BasicBlock):
51 |
52 | def __init__(self,
53 | inplanes,
54 | planes,
55 | stride=1,
56 | dilation=1,
57 | downsample=None,
58 | reduction=16,
59 | D=-1):
60 | super(SEBasicBlock, self).__init__(
61 | inplanes,
62 | planes,
63 | stride=stride,
64 | dilation=dilation,
65 | downsample=downsample,
66 | D=D)
67 | self.se = SELayer(planes, reduction=reduction, D=D)
68 |
69 | def forward(self, x):
70 | residual = x
71 |
72 | out = self.conv1(x)
73 | out = self.norm1(out)
74 | out = self.relu(out)
75 |
76 | out = self.conv2(out)
77 | out = self.norm2(out)
78 | out = self.se(out)
79 |
80 | if self.downsample is not None:
81 | residual = self.downsample(x)
82 |
83 | out += residual
84 | out = self.relu(out)
85 |
86 | return out
87 |
88 |
89 | class SEBottleneck(Bottleneck):
90 |
91 | def __init__(self,
92 | inplanes,
93 | planes,
94 | stride=1,
95 | dilation=1,
96 | downsample=None,
97 | D=3,
98 | reduction=16):
99 | super(SEBottleneck, self).__init__(
100 | inplanes,
101 | planes,
102 | stride=stride,
103 | dilation=dilation,
104 | downsample=downsample,
105 | D=D)
106 | self.se = SELayer(planes * self.expansion, reduction=reduction, D=D)
107 |
108 | def forward(self, x):
109 | residual = x
110 |
111 | out = self.conv1(x)
112 | out = self.norm1(out)
113 | out = self.relu(out)
114 |
115 | out = self.conv2(out)
116 | out = self.norm2(out)
117 | out = self.relu(out)
118 |
119 | out = self.conv3(out)
120 | out = self.norm3(out)
121 | out = self.se(out)
122 |
123 | if self.downsample is not None:
124 | residual = self.downsample(x)
125 |
126 | out += residual
127 | out = self.relu(out)
128 |
129 | return out
130 |
--------------------------------------------------------------------------------
/MinkowskiEngine/utils/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | # this software and associated documentation files (the "Software"), to deal in
5 | # the Software without restriction, including without limitation the rights to
6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | # of the Software, and to permit persons to whom the Software is furnished to do
8 | # so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in all
11 | # copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 | #
21 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | # of the code.
24 | from .quantization import sparse_quantize, ravel_hash_vec, fnv_hash_vec, unique_coordinate_map
25 | from .collation import SparseCollation, batched_coordinates, sparse_collate, batch_sparse_collate
26 | # from .coords import get_coords_map
27 | from .init import kaiming_normal_
28 | from .summary import summary
--------------------------------------------------------------------------------
/MinkowskiEngine/utils/coords.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | # this software and associated documentation files (the "Software"), to deal in
5 | # the Software without restriction, including without limitation the rights to
6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | # of the Software, and to permit persons to whom the Software is furnished to do
8 | # so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in all
11 | # copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 | #
21 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | # of the code.
24 | import torch
25 |
26 | from MinkowskiSparseTensor import SparseTensor
27 |
28 |
29 | def get_coords_map(x, y):
30 | r"""Get mapping between sparse tensor 1 and sparse tensor 2.
31 |
32 | Args:
33 | :attr:`x` (:attr:`MinkowskiEngine.SparseTensor`): a sparse tensor with
34 | `x.tensor_stride` <= `y.tensor_stride`.
35 |
36 | :attr:`y` (:attr:`MinkowskiEngine.SparseTensor`): a sparse tensor with
37 | `x.tensor_stride` <= `y.tensor_stride`.
38 |
39 | Returns:
40 | :attr:`x_indices` (:attr:`torch.LongTensor`): the indices of x that
41 | corresponds to the returned indices of y.
42 |
43 | :attr:`x_indices` (:attr:`torch.LongTensor`): the indices of y that
44 | corresponds to the returned indices of x.
45 |
46 | Example::
47 |
48 | .. code-block:: python
49 |
50 | sp_tensor = ME.SparseTensor(features, coordinates=coordinates)
51 | out_sp_tensor = stride_2_conv(sp_tensor)
52 |
53 | ins, outs = get_coords_map(sp_tensor, out_sp_tensor)
54 | for i, o in zip(ins, outs):
55 | print(f"{i} -> {o}")
56 |
57 | """
58 | assert isinstance(x, SparseTensor)
59 | assert isinstance(y, SparseTensor)
60 | assert (
61 | x.coords_man == y.coords_man
62 | ), "X and Y are using different CoordinateManagers. Y must be derived from X through strided conv/pool/etc."
63 | return x.coords_man.get_coords_map(x.coords_key, y.coords_key)
64 |
--------------------------------------------------------------------------------
/MinkowskiEngine/utils/gradcheck.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | # this software and associated documentation files (the "Software"), to deal in
5 | # the Software without restriction, including without limitation the rights to
6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | # of the Software, and to permit persons to whom the Software is furnished to do
8 | # so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in all
11 | # copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 | #
21 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | # of the code.
24 | import torch
25 |
26 | assert torch.__version__ >= "1.7.0", "Gradcheck requires pytorch 1.7 or higher"
27 |
28 | from torch.types import _TensorOrTensors
29 | from typing import Callable, Union, Optional
30 |
31 | from torch.autograd.gradcheck import gradcheck as _gradcheck
32 |
33 |
34 | def gradcheck(
35 | func: Callable[..., Union[_TensorOrTensors]], # See Note [VarArg of Tensors]
36 | inputs: _TensorOrTensors,
37 | eps: float = 1e-6,
38 | atol: float = 1e-5,
39 | rtol: float = 1e-3,
40 | raise_exception: bool = True,
41 | check_sparse_nnz: bool = False,
42 | nondet_tol: float = 0.0,
43 | check_undefined_grad: bool = True,
44 | check_grad_dtypes: bool = False,
45 | ) -> bool:
46 | return _gradcheck(
47 | lambda *x: func.apply(*x),
48 | inputs,
49 | eps=eps,
50 | atol=atol,
51 | rtol=rtol,
52 | raise_exception=raise_exception,
53 | check_sparse_nnz=check_sparse_nnz,
54 | nondet_tol=nondet_tol,
55 | check_undefined_grad=check_undefined_grad,
56 | check_grad_dtypes=check_grad_dtypes,
57 | )
58 |
--------------------------------------------------------------------------------
/MinkowskiEngine/utils/init.py:
--------------------------------------------------------------------------------
1 | import math
2 | import torch
3 |
4 |
5 | def _calculate_fan_in_and_fan_out(tensor):
6 | dimensions = tensor.dim()
7 | if dimensions < 2:
8 | raise ValueError(
9 | "Fan in and fan out can not be computed for tensor with fewer than 2 dimensions"
10 | )
11 |
12 | if dimensions == 2: # Linear
13 | fan_in = tensor.size(1)
14 | fan_out = tensor.size(0)
15 | else:
16 | num_input_fmaps = tensor.size(1)
17 | num_output_fmaps = tensor.size(2)
18 | receptive_field_size = tensor.size(0)
19 | fan_in = num_input_fmaps * receptive_field_size
20 | fan_out = num_output_fmaps * receptive_field_size
21 |
22 | return fan_in, fan_out
23 |
24 |
25 | def _calculate_correct_fan(tensor, mode):
26 | mode = mode.lower()
27 | valid_modes = ['fan_in', 'fan_out']
28 | if mode not in valid_modes:
29 | raise ValueError("Mode {} not supported, please use one of {}".format(
30 | mode, valid_modes))
31 |
32 | fan_in, fan_out = _calculate_fan_in_and_fan_out(tensor)
33 | return fan_in if mode == 'fan_in' else fan_out
34 |
35 |
36 | def kaiming_normal_(tensor, a=0, mode='fan_in', nonlinearity='leaky_relu'):
37 | fan = _calculate_correct_fan(tensor, mode)
38 | gain = torch.nn.init.calculate_gain(nonlinearity, a)
39 | std = gain / math.sqrt(fan)
40 | with torch.no_grad():
41 | return tensor.normal_(0, std)
42 |
--------------------------------------------------------------------------------
/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | # Use use previous versions, modify these variables
2 | # ARG PYTORCH="1.9.0"
3 | # ARG CUDA="11.1"
4 |
5 | ARG PYTORCH="1.12.0"
6 | ARG CUDA="11.3"
7 | ARG CUDNN="8"
8 |
9 | FROM pytorch/pytorch:${PYTORCH}-cuda${CUDA}-cudnn${CUDNN}-devel
10 |
11 | ##############################################
12 | # You should modify this to match your GPU compute capability
13 | # ENV TORCH_CUDA_ARCH_LIST="6.0 6.1 7.0+PTX"
14 | ENV TORCH_CUDA_ARCH_LIST="6.0 6.1 6.2 7.0 7.2 7.5 8.0 8.6"
15 | ##############################################
16 |
17 | ENV TORCH_NVCC_FLAGS="-Xfatbin -compress-all"
18 |
19 | # Install dependencies
20 | RUN apt-get update
21 | RUN apt-get install -y git ninja-build cmake build-essential libopenblas-dev \
22 | xterm xauth openssh-server tmux wget mate-desktop-environment-core
23 |
24 | RUN apt-get clean
25 | RUN rm -rf /var/lib/apt/lists/*
26 |
27 | # For faster build, use more jobs.
28 | ENV MAX_JOBS=4
29 | RUN git clone --recursive "https://github.com/NVIDIA/MinkowskiEngine"
30 | RUN cd MinkowskiEngine; python setup.py install --force_cuda --blas=openblas
31 |
--------------------------------------------------------------------------------
/docs/.gitignore:
--------------------------------------------------------------------------------
1 | source
2 | _build
3 | _static
4 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | SOURCEDIR = .
8 | BUILDDIR = _build
9 |
10 | # Put it first so that "make" without argument is like "make help".
11 | help:
12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
13 |
14 | .PHONY: help Makefile
15 |
16 | # Catch-all target: route all unknown targets to Sphinx using the new
17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
18 | %: Makefile
19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Documentation with Sphinx
2 |
3 | ## Install dependencies
4 | `pip install -U recommonmark sphinx sphinx_rtd_theme sphinx_markdown_tables`
5 |
6 | ## Generate curated lists only
7 | ## Automatically generate module documentations
8 | `rm -rf source && sphinx-apidoc -o source/ ../`
9 |
10 | ## Customize documentation contents
11 | Write or modify each documentation page as a markdown file.
12 | Include the markdown file in `index.rst` `toctree`.
13 | You may modify the landing page `index.rst` itself in reStructuredText format.
14 |
15 | ## Generate HTML documentation website
16 | `cp ../README.md overview.md; make html`
17 | You may ignore the consistency warning that README.md is not included in toctree. README.md is this file, the instruction to generate documentation website.
18 | The website is generated in `_build/html`
19 |
--------------------------------------------------------------------------------
/docs/_templates/layout.html:
--------------------------------------------------------------------------------
1 | {% extends '!layout.html' %}
2 | {% block document %}
3 | {{super()}}
4 |
5 |
6 |
7 |
8 |
9 |
16 |
17 | {% endblock %}
18 |
--------------------------------------------------------------------------------
/docs/benchmark.md:
--------------------------------------------------------------------------------
1 | # Benchmark
2 |
3 | We report the feed forward and backward pass time of a convolution layer, and a small U-network for v0.4.3. Note that the kernel map can be reused for other layers with the same tensor-stride, stride, and kernel offsets, thus the time reported in this page can be amortized across all layers used in a large nueral network.
4 |
5 | We use a Titan X for the experiments.
6 |
7 | ## Experiment setup
8 |
9 |
10 | For a single-convolution-layer experiment, we use the following setup.
11 |
12 |
13 | ```python
14 | import MinkowskiEngine as ME
15 |
16 | conv = ME.MinkowskiConvolution(
17 | in_channels=3,
18 | out_channels=32,
19 | kernel_size=7,
20 | stride=1,
21 | dilation=1,
22 | bias=False,
23 | dimension=3)
24 | ```
25 |
26 | We used ScanNet test set with voxel size 5cm for the experiments. As the SparseConvNet and the MinkowskiEngine use different voxelization algorithms, the number of points processed by each engine differs as well. On average, the SparseConvNet generated 25757.01 points whereas the MinkowskiEngine generated 26097.58 points over 100 ScanNet test rooms.
27 |
28 |
29 | ## Single Convolution Layer
30 |
31 | We tested the same single convolution layer with various kernel size as well. We report the average time in second each algorithm takes to process on average 25757.011 points for SparseConvNet and 26097.58 for MinkowskiEngine.
32 |
33 | | kernel size | SparseConvNet Forward | MinkowskiEngine Forward |
34 | |-------------|-----------------------|-------------------------|
35 | | 3 | 0.174 s | 0.093 s |
36 | | 5 | 0.301 s | 0.121 s |
37 | | 7 | 0.583 s | 0.165 s |
38 |
39 | | kernel size | SparseConvNet Backward | MinkowskiEngine Backward |
40 | |-------------|------------------------|--------------------------|
41 | | 3 | 0.0118 s | 0.0056 s |
42 | | 5 | 0.0287 s | 0.0149 s |
43 | | 7 | 0.0537 s | 0.0312 s |
44 |
45 |
46 | ## Simple UNet
47 |
48 | ```python
49 | net = nn.Sequential(
50 | ME.MinkowskiConvolution(
51 | in_channels=3,
52 | out_channels=32,
53 | kernel_size=5,
54 | stride=1,
55 | dilation=1,
56 | bias=False,
57 | dimension=3),
58 | ME.MinkowskiConvolution(
59 | in_channels=32,
60 | out_channels=32,
61 | kernel_size=2,
62 | stride=2,
63 | dilation=1,
64 | bias=False,
65 | dimension=3),
66 | ME.MinkowskiConvolutionTranspose
67 | in_channels=32,
68 | out_channels=32,
69 | kernel_size=2,
70 | stride=2,
71 | dilation=1,
72 | bias=False,
73 | dimension=3))
74 | ```
75 |
76 |
77 | For this experiment, we only change the kernel size of the first convolution layer.
78 |
79 | | kernel size | SparseConvNet Forward | MinkowskiEngine Forward |
80 | |-------------|-----------------------|-------------------------|
81 | | 3 | 0.1806 s | 0.1238 s |
82 | | 5 | 0.3104 s | 0.1440 s |
83 |
84 | | kernel size | SparseConvNet Backward | MinkowskiEngine Backward |
85 | |-------------|------------------------|--------------------------|
86 | | 3 | 0.0130 s | 0.0074 s |
87 | | 5 | 0.0295 s | 0.0170 s |
88 |
--------------------------------------------------------------------------------
/docs/broadcast.rst:
--------------------------------------------------------------------------------
1 | MinkowskiBroadcast
2 | ==================
3 |
4 | MinkowskiBroadcastAddition
5 | --------------------------
6 |
7 | .. autoclass:: MinkowskiEngine.MinkowskiBroadcastAddition
8 | :members: forward
9 | :undoc-members:
10 | :exclude-members:
11 |
12 | .. automethod:: __init__
13 |
14 |
15 | MinkowskiBroadcastMultiplication
16 | --------------------------------
17 |
18 | .. autoclass:: MinkowskiEngine.MinkowskiBroadcastMultiplication
19 | :members: forward
20 | :undoc-members:
21 | :exclude-members:
22 |
23 | .. automethod:: __init__
24 |
25 |
26 | MinkowskiBroadcastConcatenation
27 | -------------------------------
28 |
29 | .. autoclass:: MinkowskiEngine.MinkowskiBroadcastConcatenation
30 | :members: forward
31 | :undoc-members:
32 | :exclude-members:
33 |
34 | .. automethod:: __init__
35 |
36 |
37 | MinkowskiBroadcast
38 | ------------------
39 |
40 | .. autoclass:: MinkowskiEngine.MinkowskiBroadcast
41 | :members: forward
42 | :undoc-members:
43 | :exclude-members:
44 |
45 | .. automethod:: __init__
46 |
--------------------------------------------------------------------------------
/docs/common.rst:
--------------------------------------------------------------------------------
1 | Miscellaneous Classes
2 | =====================
3 |
4 | Kernel Generator
5 | ----------------
6 |
7 | .. autoclass:: MinkowskiEngine.KernelGenerator
8 | :members:
9 | :undoc-members:
10 |
11 | .. automethod:: __init__
12 |
13 |
14 | RegionType
15 | ----------
16 |
17 | .. autoclass:: MinkowskiEngine.RegionType
18 | :members:
19 | :undoc-members:
20 |
--------------------------------------------------------------------------------
/docs/convolution.rst:
--------------------------------------------------------------------------------
1 | MinkowskiConvolution
2 | ====================
3 |
4 | All classes defined in this class does not require :attr:`region_type`, :attr:`region_offset`, :attr:`out_coords_key`, and :attr:`axis_types`. If you provide those to the class initialization, make sure that you are providing valid arguments.
5 |
6 |
7 | MinkowskiConvolution
8 | --------------------
9 |
10 | .. autoclass:: MinkowskiEngine.MinkowskiConvolution
11 | :members: cpu, cuda, double, float, to, type, forward
12 | :undoc-members:
13 |
14 | .. automethod:: __init__
15 |
16 |
17 | MinkowskiChannelwiseConvolution
18 | -------------------------------
19 |
20 | .. autoclass:: MinkowskiEngine.MinkowskiChannelwiseConvolution
21 | :members: cpu, cuda, double, float, to, type, forward
22 | :undoc-members:
23 |
24 | .. automethod:: __init__
25 |
26 |
27 | MinkowskiConvolutionTranspose
28 | -----------------------------
29 |
30 | .. autoclass:: MinkowskiEngine.MinkowskiConvolutionTranspose
31 | :members: cpu, cuda, double, float, to, type, forward
32 | :undoc-members:
33 |
34 | .. automethod:: __init__
35 |
36 |
37 | MinkowskiGenerativeConvolutionTranspose
38 | ---------------------------------------
39 |
40 | .. autoclass:: MinkowskiEngine.MinkowskiGenerativeConvolutionTranspose
41 | :members: cpu, cuda, double, float, to, type, forward
42 | :undoc-members:
43 |
44 | .. automethod:: __init__
45 |
--------------------------------------------------------------------------------
/docs/coords.rst:
--------------------------------------------------------------------------------
1 | Coordinate Management
2 | =====================
3 |
4 | CoordinateMapKey
5 | ----------------
6 |
7 | .. autoclass:: MinkowskiEngine.CoordinateMapKey
8 | :members:
9 | :undoc-members:
10 | :exclude-members: __repr__
11 |
12 | .. automethod:: __init__
13 |
14 |
15 | CoordinateManager
16 | -----------------
17 |
18 | .. autoclass:: MinkowskiEngine.CoordinateManager
19 | :members:
20 | :undoc-members:
21 | :exclude-members: __repr__
22 |
23 | .. automethod:: __init__
24 |
25 |
26 | GPU Memory Allocator
27 | --------------------
28 |
29 | .. autoclass:: MinkowskiEngine.GPUMemoryAllocatorType
30 | :members:
31 |
32 | .. autofunction:: MinkowskiEngine.set_gpu_allocator
33 |
--------------------------------------------------------------------------------
/docs/demo/interop.rst:
--------------------------------------------------------------------------------
1 | Working with Pytorch Layers
2 | ===========================
3 |
4 | The :attr:`MinkowskiEngine.SparseTensor` is a shallow wrapper of the
5 | :attr:`torch.Tensor`. Thus, it very easy to convert a sparse tensor to a
6 | pytorch tensor and vice versa.
7 |
8 |
9 | Example: Features for Classification
10 | ------------------------------------
11 |
12 | In this example, we show how to extract features from a
13 | :attr:`MinkowskiEngine.SparseTensor` and using the features with a pytorch
14 | layer.
15 |
16 | First, let's create a network that generate a feature vector for each input in
17 | a min-batch.
18 |
19 | .. code-block:: python
20 |
21 | import torch.nn as nn
22 | import MinkowskiEngine as ME
23 |
24 |
25 | class ExampleNetwork(nn.Module):
26 |
27 | def __init__(self, in_feat, out_feat, D):
28 | self.net = nn.Sequential(
29 | ME.MinkowskiConvolution(
30 | in_channels=in_feat,
31 | out_channels=64,
32 | kernel_size=3,
33 | stride=2,
34 | dilation=1,
35 | bias=False,
36 | dimension=D), ME.MinkowskiBatchNorm(64), ME.MinkowskiReLU(),
37 | ME.MinkowskiConvolution(
38 | in_channels=64,
39 | out_channels=128,
40 | kernel_size=3,
41 | stride=2,
42 | dimension=D), ME.MinkowskiBatchNorm(128), ME.MinkowskiReLU(),
43 | ME.MinkowskiGlobalPooling(),
44 | ME.MinkowskiLinear(128, out_feat))
45 |
46 | def forward(self, x):
47 | return self.net(x)
48 |
49 |
50 | Note that the above :attr:`MinkowskiEngine.MinkowskiGlobalPooling` layer
51 | averages all features in the input sparse tensor and generate :math:`B \times
52 | D_F` when :math:`B` is the batch size (adaptively changes accordingly) and
53 | :math:`D_F` is the feature dimension of the input sparse tensor.
54 |
55 | Then, during the training, we could us the `torch.nn.CrossEntropyLoss` layer by
56 | accessing the features of the sparse tensor
57 | :attr:`MinkowskiEngine.SparseTensor.F` or
58 | :attr:`MinkowskiEngine.SparseTensor.feats`.
59 |
60 | .. code-block:: python
61 |
62 | criterion = nn.CrossEntropyLoss()
63 |
64 | for i in range(10):
65 | optimizer.zero_grad()
66 |
67 | # Get new data
68 | coords, feat, label = data_loader()
69 | input = ME.SparseTensor(features=feat, coordinates=coords, device=device)
70 | label = label.to(device)
71 |
72 | # Forward
73 | output = net(input)
74 |
75 | # Loss
76 | out_feats = output.F
77 | loss = criterion(out_feats, label)
78 |
79 | Please refer to `examples/example.py
80 | `_
81 | for the complete demo.
82 |
--------------------------------------------------------------------------------
/docs/demo/pointnet.md:
--------------------------------------------------------------------------------
1 | PointNet
2 | ========
3 |
4 | A PointNet uses a series of multi-layered perceptrons (linear layers) with
5 | spatial transformers and global pooling layers.
6 |
7 | However, you can think of a PointNet as a specialization of a convolutional
8 | neural network consisting of a series of convolution layers and global poolings.
9 | In this network, all convolution layers have kernel size 1, and stride 1. Also,
10 | the input is a sparse tensor where features are normalized coordinates.
11 |
12 | This generalization allows the network to process an arbitrary number of
13 | points, but allows you to think of linear layers as a specialization of
14 | convolution.
15 |
16 | In addition to being able to process arbitrary number of points, it allows you
17 | to define
18 |
19 | 1. Features as arbitrary generic features such as color.
20 | 2. Convolutions with kernel size > 1.
21 | 3. Convolutions with stride > 1.
22 |
23 | Please refer to the [complete pointnet example](https://github.com/NVIDIA/MinkowskiEngine/blob/master/examples/pointnet.py) for more detail.
24 |
--------------------------------------------------------------------------------
/docs/demo/segmentation.rst:
--------------------------------------------------------------------------------
1 | Semantic Segmentation
2 | =====================
3 |
4 | To run the example, please install `Open3D `_ with `pip
5 | install open3d-python`.
6 |
7 | .. code-block:: shell
8 |
9 | cd /path/to/MinkowskiEngine
10 | python -m examples.indoor
11 |
12 |
13 | Segmentation of a hotel room
14 | ----------------------------
15 |
16 | When you run the example, you will see a hotel room and semantic segmentation
17 | of the room. You can interactively rotate the visualization when you run the
18 | example. First, we load the data.
19 |
20 | .. code-block:: python
21 |
22 | def load_file(file_name):
23 | pcd = o3d.read_point_cloud(file_name)
24 | coords = np.array(pcd.points)
25 | colors = np.array(pcd.colors)
26 | return coords, colors, pcd
27 |
28 | You can provide a quantized coordinates that ensures there would be only one point per voxel, or you can use the new :attr:`MinkowskiEngine.TensorField` that does not require quantized coordinates to process point clouds. However, since it does the quanization in the main training process instead of delegating the quantization to the data loading processes, it could slow down the training.
29 | Next, you should create a batched coordinates by calling :attr:`MinkowskiEngine.utils.batched_coordinates`.
30 |
31 | .. code-block:: python
32 |
33 | # Create a batch, this process is done in a data loader during training in parallel.
34 | in_field = ME.TensorField(
35 | features=torch.from_numpy(colors).float(),
36 | coordinates=ME.utils.batched_coordinates([coords / voxel_size], dtype=torch.float32),
37 | quantization_mode=ME.SparseTensorQuantizationMode.UNWEIGHTED_AVERAGE,
38 | minkowski_algorithm=ME.MinkowskiAlgorithm.SPEED_OPTIMIZED,
39 | device=device,
40 | )
41 |
42 |
43 | Finally, we feed-forward the sparse tensor into the network and get the predictions.
44 |
45 |
46 | .. code-block:: python
47 |
48 | # Convert to a sparse tensor
49 | sinput = in_field.sparse()
50 | # Output sparse tensor
51 | soutput = model(sinput)
52 | # get the prediction on the input tensor field
53 | out_field = soutput.slice(in_field)
54 |
55 |
56 | After doing some post-processing. We can color the labels and visualize the
57 | input and the prediction side-by-side.
58 |
59 | .. image:: ../images/segmentation.png
60 |
61 |
62 | The weights are downloaded automatically once you run the example and the
63 | weights are currently the top-ranking algorithm on the `Scannet 3D segmentation
64 | benchmark `_.
65 |
66 | Please refer to the `complete indoor segmentation example
67 | `_
68 | for more detail.
69 |
--------------------------------------------------------------------------------
/docs/demo/sparse_tensor_reconstruction.rst:
--------------------------------------------------------------------------------
1 | 3D Sparsity Pattern Reconstruction
2 | ==================================
3 |
4 | In this page, we will go over a simple demo example that trains a 3D
5 | convolutional neural network that reconstructs a 3D sparsity pattern from an
6 | one-hot vector. This is similar to the `Octree Generating Networks, ICCV'17
7 | `_. The input one-hot vector indicates a 3D
8 | Computer Aided Design (CAD) chair index from the ModelNet40 dataset.
9 |
10 | We use :attr:`MinkowskiEngine.MinkowskiConvolutionTranspose` along with
11 | :attr:`MinkowskiEngine.MinkowskiPruning` to sequentially upsample a voxel by a
12 | factor of 2 and then remove some of the upsampled voxels to generate target
13 | shapes. The general network architecture looks similar to the following
14 | diagram, but the details might differ.
15 |
16 | .. image:: ../images/generative_3d_net.png
17 |
18 |
19 | Before we proceed, please go over `the training and data loading tutorial
20 | `_ first.
21 |
22 |
23 | Making a Sparsity Pattern Reconstruction Network
24 | ------------------------------------------------
25 |
26 | To create a sparse tensor defined in a 3D grid world from a vector, we need to upsample sequentially from a :math:`1 \times 1 \times 1` resolution voxel. Here, we use a block that consists of :attr:`MinkowskiEngine.MinkowskiConvolutionTranspose`, :attr:`MinkowskiEngine.MinkowskiConvolution`, and :attr:`MinkowskiEngine.MinkowskiPruning`.
27 |
28 | During a forward pass, we create two paths for 1) the main features and 2) a sparse voxel classification to remove unnecessary voxels.
29 |
30 | .. code-block:: python
31 |
32 | out = upsample_block(z)
33 | out_cls = classification(out).F
34 | out = pruning(out, out_cls > 0)
35 |
36 |
37 | Until the input sparse tensor reaches the target resolution, the network repeats a series of upsampling and pruning that removes out unnecessary voxels. We visualize the results on the following figure. Note that the final reconstruction captures the target geometry very accurately. We also visualized the hierarchical reconstruction process of upsampling and pruning.
38 |
39 | .. image:: ../images/generative_3d_results.gif
40 |
41 |
42 | Running the Example
43 | -------------------
44 |
45 | To train a network, go to the Minkowski Engine root directory, and type:
46 |
47 |
48 | .. code-block::
49 |
50 | python -m examples.reconstruction --train
51 |
52 |
53 | To visualize network predictions, or to try out a pretrained model, type:
54 |
55 | .. code-block::
56 |
57 | python -m examples.reconstruction
58 |
59 |
60 | .. image:: ../images/demo_reconstruction.png
61 |
62 | The program will visualize two 3D shapes. One on the left is the target 3D
63 | shape, one on the right is the reconstructed network prediction.
64 |
65 | The entire code can be found at `example/reconstruction.py
66 | `_.
67 |
--------------------------------------------------------------------------------
/docs/guides.md:
--------------------------------------------------------------------------------
1 | # Guidelines for Faster Networks
2 |
3 | The Minkowski Engine requires two main components for convolution on a sparse tensor: efficient kernel mapping management and operations on the features. A kernel map refers to a mapping that defines which row in an input feature maps to which row in an output feature.
4 |
5 | In Minkowski Engine, we use an unordered map whose key is a non-zero index and the corresponding row index as the value. Given two unordered maps that define input and output tensors, we can find which row maps in the input feature to which row in the output feature.
6 |
7 | However, in many cases, a convolutional network consists of repeated blocks of operations. e.g. a residual block that consists of convolutions with the same kernel size. Thus, we end up re-using a lot of kernel map and instead of re-computing every time, we cache all the kernel maps.
8 |
9 |
10 | ## Reusing the cached kernel maps
11 |
12 | As we mentioned in the previous section, the Minkowski Engine caches all kernel maps. If a network has a lot of repeated layers, such as convolutions, the network will reuse the cached kernel maps.
13 |
14 |
15 | ## Reusing the cached kernel maps for transposed layers
16 |
17 | The Minkowski Engine can reuse cached kernel maps for transposed layers by swapping the input and output of the kernel maps. For instance, if a stride-2 convolution was used on the sparse tensor with the tensor stride 2, a transposed convolution layer on the tensor stride 4 with stride 2 can reuse the same kernel map generated on the previous stride-2 convolution. Reuse as many repeated network structure as possible.
18 |
19 |
20 | ## High-dimensional convolution with cross-shaped or custom kernels
21 |
22 | As the dimension or the kernel size increases, it becomes computationally inefficient very quickly if we use hyper-cubic kernels (volumetric kernels). Try to use cross shaped kernel or other custom kernels to reduce the load. In the following snippet, we create a cross-shaped kernel for convolution.
23 |
24 | ```python
25 | import MinkowskiEngine as ME
26 |
27 | ...
28 |
29 | kernel_generator = ME.KernelGenerator(
30 | kernel_size,
31 | stride,
32 | dilation,
33 | region_type=ME.RegionType.HYPERCROSS,
34 | dimension=dimension)
35 |
36 | conv = ME.MinkowskiConvolution(
37 | in_channels=in_channels,
38 | out_channels=out_channels,
39 | kernel_size=kernel_size,
40 | stride=stride,
41 | dilation=dilation,
42 | bias=bias,
43 | kernel_generator=kernel_generator,
44 | dimension=dimension)
45 | ```
46 |
47 |
48 | ## Strided pooling layers for high-dimensional spaces
49 |
50 | In extremely high-dimensional spaces, it is very expensive to use strided convolution. Using a cross-shaped kernel is not a good solution for hierarchical maps as everything is very sparse in high-dimensional spaces and cross shaped kernel will end up being empty. Instead, use a pooling layer to create kernel map efficiently and fast.
51 |
52 | If you use a pooling layer with kernel size == strides, the MinkowskiEngine will generate kernel map very efficiently as the mapping becomes trivial.
53 |
--------------------------------------------------------------------------------
/docs/images/classification_3d_net.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NVIDIA/MinkowskiEngine/02fc608bea4c0549b0a7b00ca1bf15dee4a0b228/docs/images/classification_3d_net.png
--------------------------------------------------------------------------------
/docs/images/conv_dense.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NVIDIA/MinkowskiEngine/02fc608bea4c0549b0a7b00ca1bf15dee4a0b228/docs/images/conv_dense.gif
--------------------------------------------------------------------------------
/docs/images/conv_generalized.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NVIDIA/MinkowskiEngine/02fc608bea4c0549b0a7b00ca1bf15dee4a0b228/docs/images/conv_generalized.gif
--------------------------------------------------------------------------------
/docs/images/conv_sparse.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NVIDIA/MinkowskiEngine/02fc608bea4c0549b0a7b00ca1bf15dee4a0b228/docs/images/conv_sparse.gif
--------------------------------------------------------------------------------
/docs/images/conv_sparse_conv.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NVIDIA/MinkowskiEngine/02fc608bea4c0549b0a7b00ca1bf15dee4a0b228/docs/images/conv_sparse_conv.gif
--------------------------------------------------------------------------------
/docs/images/demo_reconstruction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NVIDIA/MinkowskiEngine/02fc608bea4c0549b0a7b00ca1bf15dee4a0b228/docs/images/demo_reconstruction.png
--------------------------------------------------------------------------------
/docs/images/detection_3d_net.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NVIDIA/MinkowskiEngine/02fc608bea4c0549b0a7b00ca1bf15dee4a0b228/docs/images/detection_3d_net.png
--------------------------------------------------------------------------------
/docs/images/generative_3d_net.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NVIDIA/MinkowskiEngine/02fc608bea4c0549b0a7b00ca1bf15dee4a0b228/docs/images/generative_3d_net.png
--------------------------------------------------------------------------------
/docs/images/generative_3d_results.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NVIDIA/MinkowskiEngine/02fc608bea4c0549b0a7b00ca1bf15dee4a0b228/docs/images/generative_3d_results.gif
--------------------------------------------------------------------------------
/docs/images/kernel_map.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NVIDIA/MinkowskiEngine/02fc608bea4c0549b0a7b00ca1bf15dee4a0b228/docs/images/kernel_map.gif
--------------------------------------------------------------------------------
/docs/images/segmentation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NVIDIA/MinkowskiEngine/02fc608bea4c0549b0a7b00ca1bf15dee4a0b228/docs/images/segmentation.png
--------------------------------------------------------------------------------
/docs/images/segmentation_3d_net.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NVIDIA/MinkowskiEngine/02fc608bea4c0549b0a7b00ca1bf15dee4a0b228/docs/images/segmentation_3d_net.png
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | Welcome to MinkowskiEngine's documentation!
2 | ===========================================
3 |
4 | The MinkowskiEngine is an auto-differentiation library for sparse tensors.
5 |
6 | Table of Contents
7 | =================
8 |
9 | .. toctree::
10 | :maxdepth: 1
11 | :caption: Introduction
12 |
13 | overview
14 | sparse_tensor_network
15 | quick_start
16 | terminology
17 |
18 | .. toctree::
19 | :maxdepth: 2
20 | :caption: Tutorials
21 |
22 | tutorial/sparse_tensor_basic
23 |
24 | .. toctree::
25 | :maxdepth: 2
26 | :caption: Demos
27 |
28 | demo/training
29 | demo/modelnet40_classification
30 | demo/segmentation
31 | demo/sparse_tensor_reconstruction
32 | demo/interop
33 | demo/multigpu
34 | demo/pointnet
35 |
36 | .. toctree::
37 | :maxdepth: 2
38 | :caption: API
39 |
40 | sparse_tensor
41 | convolution
42 | pooling
43 | broadcast
44 | normalization
45 | nonlinearity
46 | pruning
47 | interp
48 | union
49 | coords
50 | utils
51 | common
52 | misc
53 |
54 | .. toctree::
55 | :maxdepth: 1
56 | :caption: Miscellanea
57 |
58 | issues
59 | guides
60 | migration_05
61 | benchmark
62 |
63 |
64 | Indices and tables
65 | ==================
66 |
67 | * :ref:`genindex`
68 | * :ref:`search`
69 |
--------------------------------------------------------------------------------
/docs/interp.rst:
--------------------------------------------------------------------------------
1 | MinkowskiInterpolation
2 | ======================
3 |
4 |
5 | MinkowskiInterpolation
6 | ----------------------
7 |
8 | .. autoclass:: MinkowskiEngine.MinkowskiInterpolation
9 | :members: cpu, cuda, double, float, to, type, forward
10 | :undoc-members:
11 |
12 | .. automethod:: __init__
13 |
--------------------------------------------------------------------------------
/docs/migration_05.md:
--------------------------------------------------------------------------------
1 | # Migration Guide from v0.4.x to v0.5.0
2 |
3 | ## Summary
4 |
5 | ```python
6 | # 0.4
7 | ME.SparseTensor(feats=feats, coords=coords, D=3)
8 | # 0.5
9 | ME.SparseTensor(feats=feats, coords=coords, D=3)
10 | ```
11 |
12 |
13 | ```
14 | # 0.4
15 | ME.MinkowskiConvolution(..., has_bias=True)
16 | # 0.5
17 | ME.MinkowskiConvolution(..., bias=True)
18 | ```
19 |
20 |
21 | ```
22 | # 0.4
23 | RegionType.HYPERCUBE
24 | # 0.5
25 | RegionType.HYPER_CUBE
26 | ```
27 |
28 |
29 | ## Definitions
30 |
31 | ### `CoordinateMap`
32 |
33 | A coordinate map refers to a map object that converts a D-dimensional
34 | coordinate into a row index for a feature matrix where the corresponding
35 | feature for the coordinate is located. This can be implemented using
36 | `std::map`, `std::unordered_map` or a hash-table with the right hash function
37 | and the equality function.
38 |
39 | ### `CoordinateKey`
40 |
41 | A `CoordinateKey` or `CoordinateMapKey` refers to a unique identifier that can
42 | be used to retrieve a `CoordinateMap`.
43 |
44 | ### `tensor_stride`
45 |
46 | A tensor stride is a minimum distance between non-zero elements in a sparse
47 | tensor. If we take a stride-2 convolution on a sparse tensor with tensor
48 | stride 1, the resulting sparse tensor will have tensor stride 2. If we apply
49 | two stride-2 convolutions on a sparse tensor with tensor stride 3, the
50 | resulting sparse tensor will have the tensor stride 2 x 2 x 3 = 12.
51 |
52 | ## From CoordsKey to CoordinateMapKey
53 |
54 | CoordsKey should not be called in most cases, but in rare cases where you used
55 | it. Please review this section to update your code.
56 |
57 | One of the major difference is that we expose the pybind11 object directly to
58 | the python side to remove the redundant abstraction layer.
59 |
60 | In v0.4, Minkowski Engine uses a `uint64_t` hash key to identify a
61 | `CoordinateMap`, but from v0.5, we use a tensor stride
62 |
63 |
64 | ## From CoordsManager to CoordinateManager
65 |
66 | CoordinateManager should not be called in most cases, but if you do please re
67 |
68 |
69 | ### Initialization
70 |
71 | ```python
72 | # 0.4.x
73 | manager = CoordsManager(D=3)
74 | # 0.5.x
75 | manager = CoordinateManager(D=3)
76 | ```
77 |
78 | ## Initializing a new CoordinateMap
79 |
80 | ```python
81 | # 0.4.x
82 | manager = CoordsManager(D = 3)
83 | manager.initialize(torch.IntTens
84 | def initialize(self,
85 | coords: torch.IntTensor,
86 | coords_key: CoordsKey,
87 | force_creation: bool = False,
88 | force_remap: bool = False,
89 | allow_duplicate_coords: bool = False,
90 | return_inverse: bool = False) -> torch.LongTensor:
91 | ```
92 |
93 |
94 | ## Consistent Layer Arguments
95 |
--------------------------------------------------------------------------------
/docs/misc.rst:
--------------------------------------------------------------------------------
1 | Miscellanea
2 | ===========
3 |
4 | Controlling the number of threads
5 | ---------------------------------
6 |
7 | The kernel map `[1] `_ defines which row of an input feature matrix to which row of the output feature matrix. This however is an expensive operation as the dimension increases. Fortunately, some part of the operation can be parallelized and we provide a multi-threaded function to speed up this process.
8 |
9 | By default, we use all CPU threads available in the system. However, this might not be desirable in some cases. Simply define an environmental variable ``OMP_NUM_THREADS`` to control the number of threads you want to use. For example, ``export OMP_NUM_THREADS=8; python your_program.py``. If you use SLURM, the environment variable ``OMP_NUM_THREADS`` will be automatically set.
10 |
11 |
12 |
13 | is_cuda_available
14 | -----------------
15 |
16 | .. autofunction:: MinkowskiEngine.is_cuda_available
17 |
18 |
19 | cuda_version
20 | ------------
21 |
22 | .. autofunction:: MinkowskiEngine.cuda_version
23 |
24 |
25 | get_gpu_memory_info
26 | -------------------
27 |
28 | .. autofunction:: MinkowskiEngine.get_gpu_memory_info
29 |
30 |
31 | set_memory_manager_backend
32 | --------------------------
33 |
34 | .. autofunction:: MinkowskiEngine.set_memory_manager_backend
35 |
36 |
37 |
38 |
39 | References
40 | ----------
41 |
42 | - `[1] 4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural Networks, CVPR'19 `_
43 |
--------------------------------------------------------------------------------
/docs/nonlinearity.rst:
--------------------------------------------------------------------------------
1 | MinkowskiNonlinearities
2 | =======================
3 |
4 |
5 | MinkowskiReLU
6 | -------------
7 |
8 | .. autoclass:: MinkowskiEngine.MinkowskiReLU
9 | :members:
10 | :undoc-members:
11 | :exclude-members: forward
12 |
13 | .. automethod:: __init__
14 |
15 |
16 | MinkowskiPReLU
17 | --------------
18 |
19 | .. autoclass:: MinkowskiEngine.MinkowskiPReLU
20 | :members:
21 | :undoc-members:
22 | :exclude-members: forward
23 |
24 | .. automethod:: __init__
25 |
26 |
27 | MinkowskiSELU
28 | -------------
29 |
30 | .. autoclass:: MinkowskiEngine.MinkowskiSELU
31 | :members:
32 | :undoc-members:
33 | :exclude-members: forward
34 |
35 | .. automethod:: __init__
36 |
37 |
38 | MinkowskiSELU
39 | -------------
40 |
41 | .. autoclass:: MinkowskiEngine.MinkowskiSELU
42 | :members:
43 | :undoc-members:
44 | :exclude-members: forward
45 |
46 | .. automethod:: __init__
47 |
48 |
49 | MinkowskiCELU
50 | -------------
51 |
52 | .. autoclass:: MinkowskiEngine.MinkowskiCELU
53 | :members:
54 | :undoc-members:
55 | :exclude-members: forward
56 |
57 | .. automethod:: __init__
58 |
59 |
60 | MinkowskiDropout
61 | ----------------
62 |
63 | .. autoclass:: MinkowskiEngine.MinkowskiDropout
64 | :members:
65 | :undoc-members:
66 | :exclude-members: forward
67 |
68 | .. automethod:: __init__
69 |
70 |
71 | MinkowskiThreshold
72 | ------------------
73 |
74 | .. autoclass:: MinkowskiEngine.MinkowskiThreshold
75 | :members:
76 | :undoc-members:
77 | :exclude-members: forward
78 |
79 | .. automethod:: __init__
80 |
81 |
82 | MinkowskiSigmoid
83 | -----------------
84 |
85 | .. autoclass:: MinkowskiEngine.MinkowskiSigmoid
86 | :members:
87 | :undoc-members:
88 | :exclude-members: forward
89 |
90 | .. automethod:: __init__
91 |
92 |
93 | MinkowskiTanh
94 | -------------
95 |
96 | .. autoclass:: MinkowskiEngine.MinkowskiTanh
97 | :members:
98 | :undoc-members:
99 | :exclude-members: forward
100 |
101 | .. automethod:: __init__
102 |
103 |
104 | MinkowskiSoftmax
105 | ----------------
106 |
107 | .. autoclass:: MinkowskiEngine.MinkowskiSoftmax
108 | :members:
109 | :undoc-members:
110 | :exclude-members: forward
111 |
112 | .. automethod:: __init__
113 |
--------------------------------------------------------------------------------
/docs/normalization.rst:
--------------------------------------------------------------------------------
1 | MinkowskiNormalization
2 | ======================
3 |
4 |
5 | MinkowskiBatchNorm
6 | ------------------
7 |
8 | .. autoclass:: MinkowskiEngine.MinkowskiBatchNorm
9 | :members: cpu, cuda, double, float, to, type, forward
10 | :undoc-members:
11 | :exclude-members:
12 |
13 | .. automethod:: __init__
14 |
15 |
16 | MinkowskiSyncBatchNorm
17 | ----------------------
18 |
19 | .. autoclass:: MinkowskiEngine.MinkowskiSyncBatchNorm
20 | :members: cpu, cuda, double, float, to, type, forward
21 | :undoc-members:
22 | :exclude-members:
23 |
24 | .. automethod:: __init__
25 |
26 |
27 |
28 | MinkowskiInstanceNorm
29 | ---------------------
30 |
31 | .. autoclass:: MinkowskiEngine.MinkowskiInstanceNorm
32 | :members: cpu, cuda, double, float, to, type, forward
33 | :undoc-members:
34 | :exclude-members:
35 |
36 | .. automethod:: __init__
37 |
--------------------------------------------------------------------------------
/docs/pooling.rst:
--------------------------------------------------------------------------------
1 | MinkowskiPooling
2 | ================
3 |
4 | MinkowskiMaxPooling
5 | -------------------
6 |
7 | .. autoclass:: MinkowskiEngine.MinkowskiMaxPooling
8 | :members: cpu, cuda, double, float, to, type, forward
9 | :undoc-members:
10 | :exclude-members:
11 |
12 | .. automethod:: __init__
13 |
14 |
15 | MinkowskiAvgPooling
16 | -------------------
17 |
18 | .. autoclass:: MinkowskiEngine.MinkowskiAvgPooling
19 | :members: cpu, cuda, double, float, to, type, forward
20 | :undoc-members:
21 | :exclude-members:
22 |
23 | .. automethod:: __init__
24 |
25 |
26 | MinkowskiSumPooling
27 | -------------------
28 |
29 | .. autoclass:: MinkowskiEngine.MinkowskiSumPooling
30 | :members: cpu, cuda, double, float, to, type, forward
31 | :undoc-members:
32 | :exclude-members:
33 |
34 | .. automethod:: __init__
35 |
36 |
37 | MinkowskiPoolingTranspose
38 | -------------------------
39 |
40 | .. autoclass:: MinkowskiEngine.MinkowskiPoolingTranspose
41 | :members: cpu, cuda, double, float, to, type, forward
42 | :undoc-members:
43 | :exclude-members:
44 |
45 | .. automethod:: __init__
46 |
47 |
48 | MinkowskiGlobalMaxPooling
49 | -------------------------
50 |
51 | .. autoclass:: MinkowskiEngine.MinkowskiGlobalMaxPooling
52 | :members: cpu, cuda, double, float, to, type, forward
53 | :undoc-members:
54 | :exclude-members:
55 |
56 | .. automethod:: __init__
57 |
58 |
59 | MinkowskiGlobalAvgPooling
60 | -------------------------
61 |
62 | .. autoclass:: MinkowskiEngine.MinkowskiGlobalAvgPooling
63 | :members: cpu, cuda, double, float, to, type, forward
64 | :undoc-members:
65 | :exclude-members:
66 |
67 | .. automethod:: __init__
68 |
69 |
70 | MinkowskiGlobalSumPooling
71 | -------------------------
72 |
73 | .. autoclass:: MinkowskiEngine.MinkowskiGlobalSumPooling
74 | :members: cpu, cuda, double, float, to, type, forward
75 | :undoc-members:
76 | :exclude-members:
77 |
78 | .. automethod:: __init__
79 |
--------------------------------------------------------------------------------
/docs/pruning.rst:
--------------------------------------------------------------------------------
1 | MinkowskiPruning
2 | ================
3 |
4 | MinkowskiPruning
5 | ----------------
6 |
7 | .. autoclass:: MinkowskiEngine.MinkowskiPruning
8 | :members:
9 | :undoc-members:
10 |
11 | .. automethod:: __init__
12 |
--------------------------------------------------------------------------------
/docs/quick_start.md:
--------------------------------------------------------------------------------
1 | # Quick Start
2 |
3 | ## Installation
4 |
5 | The MinkowskiEngine can be installed via `pip` or using conda. Currently, the installation requirements are:
6 |
7 | - Ubuntu 14.04 or higher
8 | - CUDA 10.1 or higher if you want CUDA acceleration
9 | - pytorch 1.3 or higher
10 | - python 3.6 or higher
11 | - GCC 6 or higher
12 |
13 |
14 | ## System requirements
15 |
16 | MinkowskiEngine requires `openblas`, `python3-dev` and `torch`, `numpy` python packages. Using anaconda is highly recommended and the following instructions will install all the requirements.
17 |
18 | ## Installation
19 |
20 | The MinkowskiEngine is distributed via [PyPI MinkowskiEngine](https://pypi.org/project/MinkowskiEngine/) which can be installed simply with `pip`.
21 |
22 | ```
23 | pip3 install -U MinkowskiEngine
24 | ```
25 |
26 | To install the latest version, use `pip3 install -U git+https://github.com/NVIDIA/MinkowskiEngine`.
27 |
28 |
29 | ## Running a segmentation network
30 |
31 | Download the MinkowskiEngine and run the example code.
32 |
33 | ```
34 | git clone https://github.com/NVIDIA/MinkowskiEngine.git
35 | cd MinkowskiEngine
36 | python -m examples.indoor
37 | ```
38 |
39 | When you run the above example, it will download pretrained weights of a
40 | Minkowski network and will visualize the semantic segmentation results of a 3D scene.
41 |
42 |
43 | ## CPU only compilation
44 |
45 |
46 | ```
47 | git clone https://github.com/NVIDIA/MinkowskiEngine.git
48 | cd MinkowskiEngine
49 | python setup.py install --cpu_only
50 | ```
51 |
52 | ## Other BLAS and MKL support
53 |
54 | On intel CPU devices, `conda` installs `numpy` with `Intel Math Kernel Library` or `MKL`. The Minkowski Engine will automatically detect the MKL using `numpy` and use `MKL` instead of `openblas` or `atlas`.
55 |
56 | In many cases, this will be done automatically. However, if the numpy is not using MKL, but you have an Intel CPU, use conda to install MKL.
57 |
58 | ```
59 | conda install -c intel mkl mkl-include
60 | python setup.py install --blas=mkl
61 | ```
62 |
63 | If you want to use a specific BLAS among MKL, ATLAS, OpenBLAS, and the system BLAS, provide the blas name as follows:
64 |
65 | ```
66 | cd MinkowskiEngine
67 | python setup.py install --blas=openblas
68 | ```
69 |
--------------------------------------------------------------------------------
/docs/sparse_tensor.rst:
--------------------------------------------------------------------------------
1 | SparseTensor and TensorField
2 | ============================
3 |
4 | SparseTensor
5 | ------------
6 |
7 | .. autoclass:: MinkowskiEngine.MinkowskiSparseTensor.SparseTensor
8 | :members:
9 | :undoc-members:
10 |
11 | .. automethod:: __init__
12 |
13 |
14 | TensorField
15 | -----------
16 |
17 | .. autoclass:: MinkowskiEngine.MinkowskiTensorField.TensorField
18 | :members:
19 | :undoc-members:
20 |
21 | .. automethod:: __init__
22 |
23 |
24 | SparseTensorOperationMode
25 | -------------------------
26 |
27 | .. autoclass:: MinkowskiEngine.MinkowskiTensor.SparseTensorOperationMode
28 | :members:
29 |
30 | SparseTensorQuantizationMode
31 | ----------------------------
32 |
33 | .. autoclass:: MinkowskiEngine.MinkowskiTensor.SparseTensorQuantizationMode
34 | :members:
35 |
36 | set_sparse_tensor_operation_mode
37 | --------------------------------
38 |
39 | .. autofunction:: MinkowskiEngine.MinkowskiTensor.set_sparse_tensor_operation_mode
40 |
41 | sparse_tensor_operation_mode
42 | ----------------------------
43 |
44 | .. autofunction:: MinkowskiEngine.MinkowskiTensor.sparse_tensor_operation_mode
45 |
46 | global_coordinate_manager
47 | -------------------------
48 |
49 | .. autofunction:: MinkowskiEngine.MinkowskiTensor.global_coordinate_manager
50 |
51 | set_global_coordinate_manager
52 | -----------------------------
53 |
54 | .. autofunction:: MinkowskiEngine.MinkowskiTensor.set_global_coordinate_manager
55 |
56 | clear_global_coordinate_manager
57 | -------------------------------
58 |
59 | .. autofunction:: MinkowskiEngine.MinkowskiTensor.clear_global_coordinate_manager
60 |
--------------------------------------------------------------------------------
/docs/tutorial/convolution_basic.rst:
--------------------------------------------------------------------------------
1 | Convolution Basics
2 | ==================
3 |
4 | In this tutorial, we will cover how to use a convolution layer and
5 |
6 | Must be a positive integer or a list of positive integers.
7 |
8 | `examples/convolution.py`
9 |
--------------------------------------------------------------------------------
/docs/union.rst:
--------------------------------------------------------------------------------
1 | MinkowskiUnion
2 | ==============
3 |
4 | MinkowskiUnion
5 | --------------
6 |
7 | .. autoclass:: MinkowskiEngine.MinkowskiUnion
8 | :members: forward
9 | :undoc-members:
10 |
11 | .. automethod:: __init__
12 |
--------------------------------------------------------------------------------
/docs/utils.rst:
--------------------------------------------------------------------------------
1 | Utility Functions and Classes
2 | =============================
3 |
4 |
5 | sparse_quantize
6 | ---------------
7 |
8 | .. autofunction:: MinkowskiEngine.utils.sparse_quantize
9 |
10 |
11 | batched_coordinates
12 | -------------------
13 |
14 | .. autofunction:: MinkowskiEngine.utils.batched_coordinates
15 |
16 |
17 | sparse_collate
18 | --------------
19 |
20 | .. autofunction:: MinkowskiEngine.utils.sparse_collate
21 |
22 |
23 | batch_sparse_collate
24 | --------------------
25 |
26 | .. autofunction:: MinkowskiEngine.utils.batch_sparse_collate
27 |
28 |
29 | cat
30 | ---
31 |
32 | .. autofunction:: MinkowskiEngine.cat
33 |
34 |
35 | to_sparse
36 | ---------
37 |
38 | .. autofunction:: MinkowskiEngine.to_sparse
39 |
40 |
41 | to_sparse_all
42 | -------------
43 |
44 | .. autofunction:: MinkowskiEngine.to_sparse_all
45 |
46 |
47 | SparseCollation
48 | ---------------
49 |
50 | .. autoclass:: MinkowskiEngine.utils.SparseCollation
51 | :members:
52 | :undoc-members:
53 |
54 | .. automethod:: __init__
55 |
56 |
57 | MinkowskiToSparseTensor
58 | -----------------------
59 |
60 | .. autoclass:: MinkowskiEngine.MinkowskiToSparseTensor
61 |
62 | .. automethod:: __init__
63 |
64 |
65 | MinkowskiToDenseTensor
66 | -----------------------
67 |
68 | .. autoclass:: MinkowskiEngine.MinkowskiToDenseTensor
69 |
70 | .. automethod:: __init__
71 |
72 |
73 | MinkowskiToFeature
74 | ------------------
75 |
76 | .. autoclass:: MinkowskiEngine.MinkowskiToFeature
77 |
78 | .. automethod:: __init__
79 |
80 |
81 | MinkowskiStackCat
82 | -----------------
83 |
84 | .. autoclass:: MinkowskiEngine.MinkowskiStackCat
85 | :members: forward
86 | :undoc-members:
87 |
88 | .. automethod:: __init__
89 |
90 |
91 | MinkowskiStackSum
92 | -----------------
93 |
94 | .. autoclass:: MinkowskiEngine.MinkowskiStackSum
95 | :members: forward
96 | :undoc-members:
97 |
98 | .. automethod:: __init__
99 |
100 |
101 | MinkowskiStackMean
102 | ------------------
103 |
104 | .. autoclass:: MinkowskiEngine.MinkowskiStackMean
105 | :members: forward
106 | :undoc-members:
107 |
108 | .. automethod:: __init__
109 |
110 |
111 | MinkowskiStackVar
112 | -----------------
113 |
114 | .. autoclass:: MinkowskiEngine.MinkowskiStackVar
115 | :members: forward
116 | :undoc-members:
117 |
118 | .. automethod:: __init__
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | # Minkowski Engine Examples
2 |
3 |
4 | ## ModelNet40 Classification
5 |
6 | ```
7 | python -m examples.classification_modelnet40 --network pointnet # torch PointNet
8 | python -m examples.classification_modelnet40 --network minkpointnet # MinkowskiEngine PointNet
9 | python -m examples.classification_modelnet40 --network minkfcnn # MinkowskiEngine FCNN
10 | ```
11 |
12 | ### Training Logs
13 |
14 | - training log for MinkowskiFCNN: [https://pastebin.pl/view/30f0a0c8](https://pastebin.pl/view/30f0a0c8)
15 |
16 | ## ScanNet Semantic Segmentation
17 |
18 | ```
19 | python -m examples.indoor
20 | ```
21 |
--------------------------------------------------------------------------------
/examples/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NVIDIA/MinkowskiEngine/02fc608bea4c0549b0a7b00ca1bf15dee4a0b228/examples/__init__.py
--------------------------------------------------------------------------------
/examples/common.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | # this software and associated documentation files (the "Software"), to deal in
5 | # the Software without restriction, including without limitation the rights to
6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | # of the Software, and to permit persons to whom the Software is furnished to do
8 | # so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in all
11 | # copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 | #
21 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | # of the code.
24 | import numpy as np
25 | import random
26 | import time
27 |
28 | import torch
29 | from torch.utils.data.sampler import Sampler
30 |
31 |
32 | class Timer(object):
33 | """A simple timer."""
34 |
35 | def __init__(self):
36 | self.reset()
37 |
38 | def reset(self):
39 | self.total_time = 0
40 | self.calls = 0
41 | self.start_time = 0
42 | self.diff = 0
43 | self.averate_time = 0
44 | self.min_time = np.Inf
45 |
46 | def tic(self):
47 | # using time.time instead of time.clock because time time.clock
48 | # does not normalize for multithreading
49 | self.start_time = time.time()
50 |
51 | def toc(self, average=False):
52 | self.diff = time.time() - self.start_time
53 | self.total_time += self.diff
54 | self.calls += 1
55 | self.average_time = self.total_time / self.calls
56 | if self.diff < self.min_time:
57 | self.min_time = self.diff
58 | if average:
59 | return self.average_time
60 | else:
61 | return self.diff
62 |
63 |
64 | class InfSampler(Sampler):
65 | """Samples elements randomly, without replacement.
66 |
67 | Arguments:
68 | data_source (Dataset): dataset to sample from
69 | """
70 |
71 | def __init__(self, data_source, shuffle=False):
72 | self.data_source = data_source
73 | self.shuffle = shuffle
74 | self.reset_permutation()
75 |
76 | def reset_permutation(self):
77 | perm = len(self.data_source)
78 | if self.shuffle:
79 | perm = torch.randperm(perm)
80 | else:
81 | perm = torch.arange(perm)
82 | self._perm = perm.tolist()
83 |
84 | def __iter__(self):
85 | return self
86 |
87 | def __next__(self):
88 | if len(self._perm) == 0:
89 | self.reset_permutation()
90 | return self._perm.pop()
91 |
92 | def __len__(self):
93 | return len(self.data_source)
94 |
95 |
96 | def seed_all(random_seed):
97 | torch.manual_seed(random_seed)
98 | torch.cuda.manual_seed(random_seed)
99 | torch.cuda.manual_seed_all(random_seed)
100 | # torch.backends.cudnn.deterministic = True
101 | # torch.backends.cudnn.benchmark = False
102 | np.random.seed(random_seed)
103 | random.seed(random_seed)
104 |
--------------------------------------------------------------------------------
/examples/download_modelnet40.sh:
--------------------------------------------------------------------------------
1 | export BASE_URL=http://cvgl.stanford.edu/data2/ModelNet40/
2 |
3 | # set progress option accordingly
4 | wget --help | grep -q '\--show-progress' && \
5 | _PROGRESS_OPT="-q --show-progress" || _PROGRESS_OPT=""
6 |
7 | wget $_PROGRESS_OPT ${BASE_URL}/ModelNet40.tgz
8 | tar -xzf ModelNet40.tgz
9 | cd ModelNet40
10 | wget ${BASE_URL}/train_modelnet40.txt
11 | wget ${BASE_URL}/val_modelnet40.txt
12 | wget ${BASE_URL}/test_modelnet40.txt
--------------------------------------------------------------------------------
/examples/example.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | # this software and associated documentation files (the "Software"), to deal in
5 | # the Software without restriction, including without limitation the rights to
6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | # of the Software, and to permit persons to whom the Software is furnished to do
8 | # so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in all
11 | # copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 | #
21 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | # of the code.
24 | import torch
25 | import torch.nn as nn
26 | from torch.optim import SGD
27 |
28 | import MinkowskiEngine as ME
29 |
30 | from tests.python.common import data_loader
31 |
32 |
33 | class ExampleNetwork(ME.MinkowskiNetwork):
34 |
35 | def __init__(self, in_feat, out_feat, D):
36 | super(ExampleNetwork, self).__init__(D)
37 | self.net = nn.Sequential(
38 | ME.MinkowskiConvolution(
39 | in_channels=in_feat,
40 | out_channels=64,
41 | kernel_size=3,
42 | stride=2,
43 | dilation=1,
44 | bias=False,
45 | dimension=D), ME.MinkowskiBatchNorm(64), ME.MinkowskiReLU(),
46 | ME.MinkowskiConvolution(
47 | in_channels=64,
48 | out_channels=128,
49 | kernel_size=3,
50 | stride=2,
51 | dimension=D), ME.MinkowskiBatchNorm(128), ME.MinkowskiReLU(),
52 | ME.MinkowskiGlobalPooling(),
53 | ME.MinkowskiLinear(128, out_feat))
54 |
55 | def forward(self, x):
56 | return self.net(x)
57 |
58 |
59 | if __name__ == '__main__':
60 | # loss and network
61 | criterion = nn.CrossEntropyLoss()
62 | net = ExampleNetwork(in_feat=3, out_feat=5, D=2)
63 | print(net)
64 |
65 | # a data loader must return a tuple of coords, features, and labels.
66 | device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
67 |
68 | net = net.to(device)
69 | optimizer = SGD(net.parameters(), lr=1e-1)
70 |
71 | for i in range(10):
72 | optimizer.zero_grad()
73 |
74 | # Get new data
75 | coords, feat, label = data_loader()
76 | input = ME.SparseTensor(feat, coords, device=device)
77 | label = label.to(device)
78 |
79 | # Forward
80 | output = net(input)
81 |
82 | # Loss
83 | loss = criterion(output.F, label)
84 | print('Iteration: ', i, ', Loss: ', loss.item())
85 |
86 | # Gradient
87 | loss.backward()
88 | optimizer.step()
89 |
90 | # Saving and loading a network
91 | torch.save(net.state_dict(), 'test.pth')
92 | net.load_state_dict(torch.load('test.pth'))
93 |
--------------------------------------------------------------------------------
/examples/multigpu_ddp.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """
3 | File Name : MinkowskiEngine-multigpu_ddp
4 | date : 16/12/2019
5 | Author : wenbo
6 | Email : huwenbodut@gmail.com
7 | Description :
8 | _ _
9 | ( |---/ )
10 | ) . . (
11 | ________________________,--._(___Y___)_,--._______________________
12 | `--' `--'
13 | """
14 |
15 | import os
16 | import argparse
17 | import numpy as np
18 | from time import time
19 | from urllib.request import urlretrieve
20 | import open3d as o3d
21 | import torch
22 | import torch.nn as nn
23 | from torch.optim import SGD
24 | import torch.multiprocessing as mp
25 | import torch.distributed as dist
26 |
27 | import MinkowskiEngine as ME
28 | from examples.minkunet import MinkUNet34C
29 |
30 |
31 | if not os.path.isfile("weights.pth"):
32 | urlretrieve("http://cvgl.stanford.edu/data2/minkowskiengine/1.ply", "1.ply")
33 |
34 | parser = argparse.ArgumentParser()
35 | parser.add_argument("--file_name", type=str, default="1.ply")
36 | parser.add_argument("--batch_size", type=int, default=4)
37 | parser.add_argument("--max_ngpu", type=int, default=2)
38 |
39 | cache = {}
40 | min_time = np.inf
41 |
42 |
43 | def load_file(file_name, voxel_size):
44 | if file_name not in cache:
45 | pcd = o3d.io.read_point_cloud(file_name)
46 | cache[file_name] = pcd
47 |
48 | pcd = cache[file_name]
49 | quantized_coords, feats = ME.utils.sparse_quantize(
50 | np.array(pcd.points, dtype=np.float32),
51 | np.array(pcd.colors, dtype=np.float32),
52 | quantization_size=voxel_size,
53 | )
54 | random_labels = torch.zeros(len(feats))
55 |
56 | return quantized_coords, feats, random_labels
57 |
58 |
59 | def main():
60 | # loss and network
61 | config = parser.parse_args()
62 | num_devices = torch.cuda.device_count()
63 | num_devices = min(config.max_ngpu, num_devices)
64 | print(
65 | "Testing ",
66 | num_devices,
67 | " GPUs. Total batch size: ",
68 | num_devices * config.batch_size,
69 | )
70 |
71 | config.world_size = num_devices
72 | mp.spawn(main_worker, nprocs=num_devices, args=(num_devices, config))
73 |
74 |
75 | def main_worker(gpu, ngpus_per_node, args):
76 | global min_time
77 | args.gpu = gpu
78 | if args.gpu is not None:
79 | print("Use GPU: {} for training".format(args.gpu))
80 | args.rank = 0 * ngpus_per_node + gpu
81 | dist.init_process_group(
82 | backend="nccl",
83 | init_method="tcp://127.0.0.1:23456",
84 | world_size=args.world_size,
85 | rank=args.rank,
86 | )
87 | # create model
88 | model = MinkUNet34C(3, 20, D=3)
89 | torch.cuda.set_device(args.gpu)
90 | model.cuda(args.gpu)
91 | model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[args.gpu])
92 | # define loss function (criterion) and optimizer
93 | criterion = nn.CrossEntropyLoss().cuda(args.gpu)
94 | # Synchronized batch norm
95 | net = ME.MinkowskiSyncBatchNorm.convert_sync_batchnorm(model)
96 | optimizer = SGD(net.parameters(), lr=1e-1)
97 |
98 | for iteration in range(10):
99 | optimizer.zero_grad()
100 |
101 | # Get new data
102 | # inputs, labels = [], []
103 | batch = [load_file(args.file_name, 0.05) for _ in range(args.batch_size)]
104 | coordinates_, featrues_, random_labels = list(zip(*batch))
105 | coordinates, features = ME.utils.sparse_collate(coordinates_, featrues_)
106 | inputs = ME.SparseTensor(features, coordinates, device=args.gpu)
107 | labels = torch.cat(random_labels).long().to(args.gpu)
108 | # The raw version of the parallel_apply
109 | st = time()
110 | outputs = net(inputs)
111 | # Extract features from the sparse tensors to use a pytorch criterion
112 | out_features = outputs.F
113 | loss = criterion(out_features, labels)
114 | # Gradient
115 | loss.backward()
116 | optimizer.step()
117 |
118 | t = torch.tensor(time() - st, dtype=torch.float).cuda(args.gpu)
119 | dist.all_reduce(t)
120 | min_time = min(t.detach().cpu().numpy() / ngpus_per_node, min_time)
121 | print(
122 | f"Iteration: {iteration}, Loss: {loss.item()}, Time: {t.detach().item()}, Min time: {min_time}"
123 | )
124 |
125 | # Must clear cache at regular interval
126 | if iteration % 10 == 0:
127 | torch.cuda.empty_cache()
128 |
129 |
130 | if __name__ == "__main__":
131 | main()
132 |
--------------------------------------------------------------------------------
/examples/stack_unet.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | # this software and associated documentation files (the "Software"), to deal in
5 | # the Software without restriction, including without limitation the rights to
6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | # of the Software, and to permit persons to whom the Software is furnished to do
8 | # so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in all
11 | # copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 | #
21 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | # of the code.
24 | import torch
25 | import torch.nn as nn
26 |
27 | import MinkowskiEngine as ME
28 | import MinkowskiEngine.MinkowskiFunctional as MF
29 |
30 | from tests.python.common import data_loader
31 |
32 |
33 | class StackUNet(ME.MinkowskiNetwork):
34 | def __init__(self, in_nchannel, out_nchannel, D):
35 | ME.MinkowskiNetwork.__init__(self, D)
36 | channels = [in_nchannel, 16, 32]
37 | self.net = nn.Sequential(
38 | ME.MinkowskiStackSum(
39 | ME.MinkowskiConvolution(
40 | channels[0],
41 | channels[1],
42 | kernel_size=3,
43 | stride=1,
44 | dimension=D,
45 | ),
46 | nn.Sequential(
47 | ME.MinkowskiConvolution(
48 | channels[0],
49 | channels[1],
50 | kernel_size=3,
51 | stride=2,
52 | dimension=D,
53 | ),
54 | ME.MinkowskiStackSum(
55 | nn.Identity(),
56 | nn.Sequential(
57 | ME.MinkowskiConvolution(
58 | channels[1],
59 | channels[2],
60 | kernel_size=3,
61 | stride=2,
62 | dimension=D,
63 | ),
64 | ME.MinkowskiConvolutionTranspose(
65 | channels[2],
66 | channels[1],
67 | kernel_size=3,
68 | stride=1,
69 | dimension=D,
70 | ),
71 | ME.MinkowskiPoolingTranspose(
72 | kernel_size=2, stride=2, dimension=D
73 | ),
74 | ),
75 | ),
76 | ME.MinkowskiPoolingTranspose(kernel_size=2, stride=2, dimension=D),
77 | ),
78 | ),
79 | ME.MinkowskiToFeature(),
80 | nn.Linear(channels[1], out_nchannel, bias=True),
81 | )
82 |
83 | def forward(self, x):
84 | return self.net(x)
85 |
86 |
87 | if __name__ == "__main__":
88 | # loss and network
89 | net = StackUNet(3, 5, D=2)
90 | print(net)
91 |
92 | # a data loader must return a tuple of coords, features, and labels.
93 | coords, feat, label = data_loader()
94 | device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
95 |
96 | net = net.to(device)
97 | input = ME.SparseTensor(feat, coords, device=device)
98 |
99 | # Forward
100 | output = net(input)
101 |
--------------------------------------------------------------------------------
/examples/unet.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | # this software and associated documentation files (the "Software"), to deal in
5 | # the Software without restriction, including without limitation the rights to
6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | # of the Software, and to permit persons to whom the Software is furnished to do
8 | # so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in all
11 | # copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 | #
21 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | # of the code.
24 | import torch
25 |
26 | import MinkowskiEngine as ME
27 | import MinkowskiEngine.MinkowskiFunctional as MF
28 |
29 | from tests.python.common import data_loader
30 |
31 |
32 | class UNet(ME.MinkowskiNetwork):
33 |
34 | def __init__(self, in_nchannel, out_nchannel, D):
35 | super(UNet, self).__init__(D)
36 | self.block1 = torch.nn.Sequential(
37 | ME.MinkowskiConvolution(
38 | in_channels=in_nchannel,
39 | out_channels=8,
40 | kernel_size=3,
41 | stride=1,
42 | dimension=D),
43 | ME.MinkowskiBatchNorm(8))
44 |
45 | self.block2 = torch.nn.Sequential(
46 | ME.MinkowskiConvolution(
47 | in_channels=8,
48 | out_channels=16,
49 | kernel_size=3,
50 | stride=2,
51 | dimension=D),
52 | ME.MinkowskiBatchNorm(16),
53 | )
54 |
55 | self.block3 = torch.nn.Sequential(
56 | ME.MinkowskiConvolution(
57 | in_channels=16,
58 | out_channels=32,
59 | kernel_size=3,
60 | stride=2,
61 | dimension=D),
62 | ME.MinkowskiBatchNorm(32))
63 |
64 | self.block3_tr = torch.nn.Sequential(
65 | ME.MinkowskiConvolutionTranspose(
66 | in_channels=32,
67 | out_channels=16,
68 | kernel_size=3,
69 | stride=2,
70 | dimension=D),
71 | ME.MinkowskiBatchNorm(16))
72 |
73 | self.block2_tr = torch.nn.Sequential(
74 | ME.MinkowskiConvolutionTranspose(
75 | in_channels=32,
76 | out_channels=16,
77 | kernel_size=3,
78 | stride=2,
79 | dimension=D),
80 | ME.MinkowskiBatchNorm(16))
81 |
82 | self.conv1_tr = ME.MinkowskiConvolution(
83 | in_channels=24,
84 | out_channels=out_nchannel,
85 | kernel_size=1,
86 | stride=1,
87 | dimension=D)
88 |
89 | def forward(self, x):
90 | out_s1 = self.block1(x)
91 | out = MF.relu(out_s1)
92 |
93 | out_s2 = self.block2(out)
94 | out = MF.relu(out_s2)
95 |
96 | out_s4 = self.block3(out)
97 | out = MF.relu(out_s4)
98 |
99 | out = MF.relu(self.block3_tr(out))
100 | out = ME.cat(out, out_s2)
101 |
102 | out = MF.relu(self.block2_tr(out))
103 | out = ME.cat(out, out_s1)
104 |
105 | return self.conv1_tr(out)
106 |
107 |
108 | if __name__ == '__main__':
109 | # loss and network
110 | net = UNet(3, 5, D=2)
111 | print(net)
112 |
113 | # a data loader must return a tuple of coords, features, and labels.
114 | coords, feat, label = data_loader()
115 | device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
116 |
117 | net = net.to(device)
118 | input = ME.SparseTensor(feat, coords, device=device)
119 |
120 | # Forward
121 | output = net(input)
122 |
--------------------------------------------------------------------------------
/pybind/minkowski.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020 NVIDIA Corporation.
3 | * Copyright (c) 2018-2020 Chris Choy (chrischoy@ai.stanford.edu).
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in
13 | * all copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 | * IN THE SOFTWARE.
22 | *
23 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
24 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
25 | * of the code.
26 | */
27 | #include
28 |
29 | #include
30 |
31 | #include
32 | #include
33 |
34 | #include "extern.hpp"
35 |
36 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
37 | // Constant function
38 | m.def("is_cuda_available", &is_cuda_available);
39 | m.def("cuda_version", &cuda_version);
40 | m.def("cudart_version", &cudart_version);
41 | m.def("get_gpu_memory_info", &get_gpu_memory_info);
42 |
43 | initialize_non_templated_classes(m);
44 |
45 | // Manager
46 | instantiate_manager>(m,
47 | std::string("CPU"));
48 | #ifndef CPU_ONLY
49 | instantiate_manager>(
50 | m, std::string("GPU_default"));
51 | instantiate_manager>(
52 | m, std::string("GPU_c10"));
53 | #endif
54 |
55 | // Functions
56 | non_templated_cpu_func(m);
57 | instantiate_cpu_func(m, "");
58 |
59 | #ifndef CPU_ONLY
60 | instantiate_gpu_func(
61 | m, std::string(""));
62 |
63 | instantiate_gpu_func(
64 | m, std::string(""));
65 |
66 | non_templated_gpu_func(m);
67 | #endif
68 | }
69 |
--------------------------------------------------------------------------------
/pybind/minkowski.cu:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020 NVIDIA Corporation.
3 | * Copyright (c) 2018-2020 Chris Choy (chrischoy@ai.stanford.edu).
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in
13 | * all copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 | * IN THE SOFTWARE.
22 | *
23 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
24 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
25 | * of the code.
26 | */
27 | #include "extern.hpp"
28 |
29 | #include
30 |
31 | #include
32 |
33 | #include
34 | #include
35 |
36 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
37 | // Constant function
38 | m.def("is_cuda_available", &is_cuda_available);
39 | m.def("cuda_version", &cuda_version);
40 | m.def("cudart_version", &cudart_version);
41 | m.def("get_gpu_memory_info", &get_gpu_memory_info);
42 |
43 | initialize_non_templated_classes(m);
44 |
45 | // Manager
46 | instantiate_manager>(m,
47 | std::string("CPU"));
48 | #ifndef CPU_ONLY
49 | instantiate_manager>(
50 | m, std::string("GPU_default"));
51 | instantiate_manager>(
52 | m, std::string("GPU_c10"));
53 | #endif
54 |
55 | // Functions
56 | non_templated_cpu_func(m);
57 | instantiate_cpu_func(m, "");
58 |
59 | #ifndef CPU_ONLY
60 | instantiate_gpu_func(
61 | m, std::string(""));
62 |
63 | instantiate_gpu_func(
64 | m, std::string(""));
65 |
66 | non_templated_gpu_func(m);
67 | #endif
68 | }
69 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | numpy
2 | torch>=1.4,<1.7
3 |
--------------------------------------------------------------------------------
/src/3rdparty/cudf/detail/nvtx/ranges.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020, NVIDIA CORPORATION.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #pragma once
18 |
19 | #include "nvtx3.hpp"
20 |
21 | namespace cudf {
22 | /**
23 | * @brief Tag type for libcudf's NVTX domain.
24 | *
25 | */
26 | struct libcudf_domain {
27 | static constexpr char const* name{"libcudf"}; ///< Name of the libcudf domain
28 | };
29 |
30 | /**
31 | * @brief Alias for an NVTX range in the libcudf domain.
32 | *
33 | */
34 | using thread_range = ::nvtx3::domain_thread_range;
35 |
36 | } // namespace cudf
37 |
38 | /**
39 | * @brief Convenience macro for generating an NVTX range in the `libcudf` domain
40 | * from the lifetime of a function.
41 | *
42 | * Uses the name of the immediately enclosing function returned by `__func__` to
43 | * name the range.
44 | *
45 | * Example:
46 | * ```
47 | * void some_function(){
48 | * CUDF_FUNC_RANGE();
49 | * ...
50 | * }
51 | * ```
52 | *
53 | */
54 | #define CUDF_FUNC_RANGE() NVTX3_FUNC_RANGE_IN(cudf::libcudf_domain)
55 |
--------------------------------------------------------------------------------
/src/3rdparty/cudf/detail/utilities/device_operators.cuh:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019, NVIDIA CORPORATION.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #ifndef DEVICE_OPERATORS_CUH
18 | #define DEVICE_OPERATORS_CUH
19 |
20 | /** ---------------------------------------------------------------------------*
21 | * @brief definition of the device operators
22 | * @file device_operators.cuh
23 | *
24 | * ---------------------------------------------------------------------------**/
25 |
26 | #include
27 | #include
28 |
29 | namespace cudf {
30 | // ------------------------------------------------------------------------
31 | // Binary operators
32 | /* @brief binary `sum` operator */
33 | struct DeviceSum {
34 | template
35 | CUDA_HOST_DEVICE_CALLABLE T operator()(const T& lhs, const T& rhs)
36 | {
37 | return lhs + rhs;
38 | }
39 |
40 | template
41 | static constexpr T identity()
42 | {
43 | return T{0};
44 | }
45 | };
46 |
47 | /* @brief `count` operator - used in rolling windows */
48 | struct DeviceCount {
49 | template
50 | CUDA_HOST_DEVICE_CALLABLE T operator()(const T&, const T& rhs)
51 | {
52 | return rhs + T{1};
53 | }
54 |
55 | template
56 | static constexpr T identity()
57 | {
58 | return T{0};
59 | }
60 | };
61 |
62 | /**
63 | * @brief string value for sentinel which is used in min, max reduction
64 | * operators
65 | * This sentinel string value is the highest possible valid UTF-8 encoded
66 | * character. This serves as identity value for maximum operator on string
67 | * values. Also, this char pointer serves as valid device pointer of identity
68 | * value for minimum operator on string values.
69 | *
70 | */
71 | __constant__ char max_string_sentinel[5]{"\xF7\xBF\xBF\xBF"};
72 |
73 | /* @brief binary `min` operator */
74 | struct DeviceMin {
75 | template
76 | CUDA_HOST_DEVICE_CALLABLE T operator()(const T& lhs, const T& rhs)
77 | {
78 | return std::min(lhs, rhs);
79 | }
80 |
81 | template
82 | static constexpr T identity()
83 | {
84 | return std::numeric_limits::max();
85 | }
86 | };
87 |
88 | /* @brief binary `max` operator */
89 | struct DeviceMax {
90 | template
91 | CUDA_HOST_DEVICE_CALLABLE T operator()(const T& lhs, const T& rhs)
92 | {
93 | return std::max(lhs, rhs);
94 | }
95 |
96 | template
97 | static constexpr T identity()
98 | {
99 | return std::numeric_limits::lowest();
100 | }
101 | };
102 |
103 | /* @brief binary `product` operator */
104 | struct DeviceProduct {
105 | template
106 | CUDA_HOST_DEVICE_CALLABLE T operator()(const T& lhs, const T& rhs)
107 | {
108 | return lhs * rhs;
109 | }
110 |
111 | template
112 | static constexpr T identity()
113 | {
114 | return T{1};
115 | }
116 | };
117 |
118 | /* @brief binary `and` operator */
119 | struct DeviceAnd {
120 | template ::value>* = nullptr>
121 | CUDA_HOST_DEVICE_CALLABLE T operator()(const T& lhs, const T& rhs)
122 | {
123 | return (lhs & rhs);
124 | }
125 | };
126 |
127 | /* @brief binary `or` operator */
128 | struct DeviceOr {
129 | template ::value>* = nullptr>
130 | CUDA_HOST_DEVICE_CALLABLE T operator()(const T& lhs, const T& rhs)
131 | {
132 | return (lhs | rhs);
133 | }
134 | };
135 |
136 | /* @brief binary `xor` operator */
137 | struct DeviceXor {
138 | template ::value>* = nullptr>
139 | CUDA_HOST_DEVICE_CALLABLE T operator()(const T& lhs, const T& rhs)
140 | {
141 | return (lhs ^ rhs);
142 | }
143 | };
144 |
145 | } // namespace cudf
146 |
147 | #endif
148 |
--------------------------------------------------------------------------------
/src/3rdparty/hash/hash_allocator.cuh:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2017, NVIDIA CORPORATION.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #ifndef HASH_ALLOCATOR_CUH
18 | #define HASH_ALLOCATOR_CUH
19 |
20 | #include
21 | #include
22 |
23 | template
24 | struct managed_allocator {
25 | typedef T value_type;
26 | // rmm::mr::device_memory_resource* mr = new rmm::mr::managed_memory_resource;
27 |
28 | managed_allocator() = default;
29 |
30 | template
31 | constexpr managed_allocator(const managed_allocator&) noexcept
32 | {
33 | }
34 |
35 | T* allocate(std::size_t n, cudaStream_t stream = 0) const
36 | {
37 | T* d_tmp;
38 | cudaError_t error = cudaMalloc((void**) &d_tmp, n * sizeof(T));
39 | if (error != cudaSuccess) {
40 | cudaGetLastError(); // clear CUDA error
41 | std::runtime_error("cudaMalloc failed in the hash_allocator.cuh:managed_allocator.");
42 | }
43 | return d_tmp;
44 | // return static_cast(mr->allocate(n * sizeof(T), stream));
45 | }
46 |
47 | void deallocate(T* p, std::size_t n, cudaStream_t stream = 0) const
48 | {
49 | cudaFree(p);
50 | //mr->deallocate(p, n * sizeof(T), stream);
51 | }
52 | };
53 |
54 | template
55 | bool operator==(const managed_allocator&, const managed_allocator&)
56 | {
57 | return true;
58 | }
59 | template
60 | bool operator!=(const managed_allocator&, const managed_allocator&)
61 | {
62 | return false;
63 | }
64 |
65 | template
66 | struct default_allocator {
67 | typedef T value_type;
68 | // rmm::mr::device_memory_resource* mr = rmm::mr::get_default_resource();
69 |
70 | default_allocator() = default;
71 |
72 | template
73 | constexpr default_allocator(const default_allocator&) noexcept
74 | {
75 | }
76 |
77 | T* allocate(std::size_t n, cudaStream_t stream = 0) const
78 | {
79 | T* d_tmp;
80 | cudaError_t error = cudaMalloc((void**) &d_tmp, n * sizeof(T));
81 | if (error != cudaSuccess) {
82 | cudaGetLastError(); // clear CUDA error
83 | std::runtime_error("cudaMalloc failed in the hash_allocator.cuh:default_allocator.");
84 | }
85 |
86 | return d_tmp;
87 | // return static_cast(mr->allocate(n * sizeof(T), stream));
88 | }
89 |
90 | void deallocate(T* p, std::size_t n, cudaStream_t stream = 0) const
91 | {
92 | cudaFree(p);
93 | // mr->deallocate(p, n * sizeof(T), stream);
94 | }
95 | };
96 |
97 | template
98 | bool operator==(const default_allocator&, const default_allocator&)
99 | {
100 | return true;
101 | }
102 | template
103 | bool operator!=(const default_allocator&, const default_allocator&)
104 | {
105 | return false;
106 | }
107 |
108 | #endif
109 |
--------------------------------------------------------------------------------
/src/3rdparty/hash/managed.cuh:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2017, NVIDIA CORPORATION.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #ifndef MANAGED_CUH
18 | #define MANAGED_CUH
19 |
20 | #include
21 | #include
22 |
23 | struct managed {
24 | static void *operator new(size_t n)
25 | {
26 | void *ptr = 0;
27 | cudaError_t result = cudaMallocManaged(&ptr, n);
28 | if (cudaSuccess != result || 0 == ptr) throw std::bad_alloc();
29 | return ptr;
30 | }
31 |
32 | static void operator delete(void *ptr) noexcept
33 | {
34 | auto const free_result = cudaFree(ptr);
35 | assert(free_result == cudaSuccess);
36 | }
37 | };
38 |
39 | inline bool isPtrManaged(cudaPointerAttributes attr)
40 | {
41 | #if CUDART_VERSION >= 10000
42 | return (attr.type == cudaMemoryTypeManaged);
43 | #else
44 | return attr.isManaged;
45 | #endif
46 | }
47 |
48 | #endif // MANAGED_CUH
49 |
--------------------------------------------------------------------------------
/src/broadcast_kernel.cuh:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | * copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 | * IN THE SOFTWARE.
20 | *
21 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | * of the code.
24 | */
25 | #ifndef BROADCAST_CUH
26 | #define BROADCAST_CUH
27 |
28 | #include
29 | #include
30 | #include
31 |
32 | #include "gpu.cuh"
33 | #include "kernel_map.cuh"
34 | #include "math_functions.cuh"
35 | #include "types.hpp"
36 |
37 | namespace minkowski {
38 |
39 | template
40 | void BroadcastForwardKernelGPU(
41 | const Dtype *d_in_feat, int in_nrows, const Dtype *d_in_feat_global,
42 | int in_nrows_global, Dtype *d_out_feat, int nchannel,
43 | BroadcastMode::Type const op,
44 | gpu_kernel_map const &kernel_map,
45 | cusparseHandle_t cushandle, cudaStream_t stream);
46 |
47 | template
48 | void BroadcastBackwardKernelGPU(
49 | const Dtype *d_in_feat, Dtype *d_grad_in_feat, int in_nrows,
50 | const Dtype *d_in_feat_global, Dtype *d_grad_in_feat_global,
51 | int in_nrows_global, const Dtype *d_grad_out_feat, int nchannel,
52 | BroadcastMode::Type const op,
53 | gpu_kernel_map const &kernel_map,
54 | cusparseHandle_t cushandle, cudaStream_t stream);
55 |
56 | } // namespace minkowski
57 |
58 | #endif
59 |
--------------------------------------------------------------------------------
/src/common.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | * copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 | * IN THE SOFTWARE.
20 | *
21 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | * of the code.
24 | */
25 | #ifndef COMMON
26 | #define COMMON
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | #include
33 |
34 | #include "types.hpp"
35 | #include "utils.hpp"
36 |
37 | #include "coords_key.hpp"
38 | #include "coords_manager.hpp"
39 |
40 | #ifndef CPU_ONLY
41 | #include
42 | #include
43 | #include
44 | #include
45 | #include
46 | #include // cuda driver types
47 |
48 | #include
49 |
50 | #include "gpu.cuh"
51 | #include "types.cuh"
52 | #include "gpu_memory_manager.hpp"
53 | #endif
54 |
55 | #endif // COMMON
56 |
--------------------------------------------------------------------------------
/src/convolution_kernel.cuh:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | * copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 | * IN THE SOFTWARE.
20 | *
21 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | * of the code.
24 | */
25 | #ifndef CONVOLUTION_CUH
26 | #define CONVOLUTION_CUH
27 |
28 | #include
29 | #include
30 |
31 | #include "gpu.cuh"
32 | #include "kernel_map.cuh"
33 | #include "math_functions.cuh"
34 | #include "types.hpp"
35 |
36 | namespace minkowski {
37 |
38 | template
39 | void ConvolutionForwardKernelGPU(
40 | Dtype const *d_in_feat, //
41 | default_types::size_type const in_nchannel, //
42 | Dtype *d_out_feat, //
43 | default_types::size_type const out_nchannel, //
44 | Dtype *d_kernel, gpu_kernel_map const &kernel_map,
45 | default_types::size_type const in_nrows, //
46 | default_types::size_type const out_nrows, //
47 | ByteAllocator &allocator, //
48 | MinkowskiAlgorithm::Mode const algo_index, //
49 | ConvolutionMode::Type const convolution_mode, //
50 | cublasHandle_t cuhandle, cudaStream_t stream);
51 |
52 | template
53 | void ConvolutionBackwardKernelGPU(
54 | Dtype const *d_in_feat, //
55 | Dtype *d_grad_in_feat, //
56 | default_types::size_type const in_nchannel, //
57 | Dtype const *d_grad_out_feat, //
58 | default_types::size_type const out_nchannel, //
59 | Dtype const *d_kernel, //
60 | Dtype *d_grad_kernel, //
61 | gpu_kernel_map const &kernel_map,
62 | default_types::size_type const in_nrows, //
63 | default_types::size_type const out_nrows, //
64 | ByteAllocator &allocator, //
65 | MinkowskiAlgorithm::Mode const algo_index, //
66 | ConvolutionMode::Type const convolution_mode, //
67 | cublasHandle_t cuhandle, cudaStream_t stream);
68 | } // end namespace minkowski
69 |
70 | #endif // end CONVOLUTION_CUH
71 |
--------------------------------------------------------------------------------
/src/dispatcher.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | namespace minkowski {
14 |
15 | #define MINK_PRIVATE_CASE_TYPE_USING_HINT(NAME, enum_type, type, HINT, ...) \
16 | case enum_type: { \
17 | using HINT = type; \
18 | return __VA_ARGS__(); \
19 | }
20 |
21 | #define MINK_PRIVATE_CASE_TYPE(NAME, enum_type, type, HINT, ...) \
22 | MINK_PRIVATE_CASE_TYPE_USING_HINT(NAME, enum_type, type, HINT, __VA_ARGS__)
23 |
24 | #define MINK_DISPATCH_INTEGER_TYPES(TYPE, HINT, NAME, ...) \
25 | [&] { \
26 | const auto &the_type = TYPE; \
27 | /* don't use TYPE again in case it is an expensive or side-effect op */ \
28 | at::ScalarType _it = ::detail::scalar_type(the_type); \
29 | switch (_it) { \
30 | MINK_PRIVATE_CASE_TYPE(NAME, at::ScalarType::Int, int32_t, HINT, \
31 | __VA_ARGS__) \
32 | MINK_PRIVATE_CASE_TYPE(NAME, at::ScalarType::Long, int64_t, HINT, \
33 | __VA_ARGS__) \
34 | default: \
35 | AT_ERROR(#NAME, " not implemented for '", toString(_it), "'"); \
36 | } \
37 | }()
38 |
39 | } // namespace minkowski
40 |
--------------------------------------------------------------------------------
/src/errors.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020 NVIDIA CORPORATION.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
23 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
24 | * of the code.
25 | */
26 | #ifndef ERRORS_HPP
27 | #define ERRORS_HPP
28 |
29 | #include
30 |
31 | namespace minkowski {
32 |
33 | constexpr char const * const ERROR_MAP_NOT_FOUND = "CoordinateMap not found";
34 |
35 | constexpr char const * const ERROR_NOT_IMPLEMENTED = "Not implemented";
36 |
37 | constexpr char const * const ERROR_CPU_ONLY = "Compiled with only CPU backend.";
38 |
39 | } // end minkowski
40 |
41 | #endif
42 |
--------------------------------------------------------------------------------
/src/gpu.cu:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020 NVIDIA CORPORATION.
3 | * Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in
13 | * all copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 | * IN THE SOFTWARE.
22 | *
23 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
24 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
25 | * of the code.
26 | */
27 | #include
28 | #include
29 | #include
30 |
31 | #include "gpu.cuh"
32 |
33 | namespace minkowski {
34 |
35 | const char *cublasGetErrorString(cublasStatus_t error) {
36 | switch (error) {
37 | case CUBLAS_STATUS_SUCCESS:
38 | return "CUBLAS_STATUS_SUCCESS";
39 | case CUBLAS_STATUS_NOT_INITIALIZED:
40 | return "CUBLAS_STATUS_NOT_INITIALIZED";
41 | case CUBLAS_STATUS_ALLOC_FAILED:
42 | return "CUBLAS_STATUS_ALLOC_FAILED";
43 | case CUBLAS_STATUS_INVALID_VALUE:
44 | return "CUBLAS_STATUS_INVALID_VALUE";
45 | case CUBLAS_STATUS_ARCH_MISMATCH:
46 | return "CUBLAS_STATUS_ARCH_MISMATCH";
47 | case CUBLAS_STATUS_MAPPING_ERROR:
48 | return "CUBLAS_STATUS_MAPPING_ERROR";
49 | case CUBLAS_STATUS_EXECUTION_FAILED:
50 | return "CUBLAS_STATUS_EXECUTION_FAILED";
51 | case CUBLAS_STATUS_INTERNAL_ERROR:
52 | return "CUBLAS_STATUS_INTERNAL_ERROR";
53 | #if CUDA_VERSION >= 6000
54 | case CUBLAS_STATUS_NOT_SUPPORTED:
55 | return "CUBLAS_STATUS_NOT_SUPPORTED";
56 | #endif
57 | #if CUDA_VERSION >= 6050
58 | case CUBLAS_STATUS_LICENSE_ERROR:
59 | return "CUBLAS_STATUS_LICENSE_ERROR";
60 | #endif
61 | }
62 | return "Unknown cublas status";
63 | }
64 |
65 | const char *cusparseGetErrorString(cusparseStatus_t error) {
66 | // Read more at: http://docs.nvidia.com/cuda/cusparse/index.html#ixzz3f79JxRar
67 | switch (error) {
68 | case CUSPARSE_STATUS_SUCCESS:
69 | return "The operation completed successfully.";
70 | case CUSPARSE_STATUS_NOT_INITIALIZED:
71 | return "CUSPARSE_STATUS_NOT_INITIALIZED";
72 |
73 | case CUSPARSE_STATUS_ALLOC_FAILED:
74 | return "CUSPARSE_STATUS_ALLOC_FAILED";
75 |
76 | case CUSPARSE_STATUS_INVALID_VALUE:
77 | return "CUSPARSE_STATUS_INVALID_VALUE";
78 |
79 | case CUSPARSE_STATUS_ARCH_MISMATCH:
80 | return "CUSPARSE_STATUS_ARCH_MISMATCH";
81 |
82 | case CUSPARSE_STATUS_MAPPING_ERROR:
83 | return "CUSPARSE_STATUS_MAPPING_ERROR";
84 |
85 | case CUSPARSE_STATUS_EXECUTION_FAILED:
86 | return "CUSPARSE_STATUS_EXECUTION_FAILED";
87 |
88 | case CUSPARSE_STATUS_INTERNAL_ERROR:
89 | return "CUSPARSE_STATUS_INTERNAL_ERROR";
90 |
91 | case CUSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
92 | return "CUSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED";
93 | }
94 |
95 | return "";
96 | }
97 |
98 | cusparseHandle_t getCurrentCUDASparseHandle() {
99 | cusparseHandle_t handle;
100 | CUSPARSE_CHECK(cusparseCreate(&handle));
101 | return handle;
102 | }
103 |
104 | static std::string format_size(uint64_t size) {
105 | std::ostringstream os;
106 | os.precision(2);
107 | os << std::fixed;
108 | if (size <= 1024) {
109 | os << size << " bytes";
110 | } else if (size <= 1048576) {
111 | os << (size / 1024.0);
112 | os << " KiB";
113 | } else if (size <= 1073741824ULL) {
114 | os << size / 1048576.0;
115 | os << " MiB";
116 | } else {
117 | os << size / 1073741824.0;
118 | os << " GiB";
119 | }
120 | return os.str();
121 | }
122 |
123 | std::pair get_memory_info() {
124 | size_t device_free;
125 | size_t device_total;
126 | CUDA_CHECK(cudaMemGetInfo(&device_free, &device_total));
127 | return std::make_pair(device_total, device_free);
128 | }
129 |
130 | } // end namespace minkowski
131 |
--------------------------------------------------------------------------------
/src/kernel_map.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020 NVIDIA Corporation.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 | * IN THE SOFTWARE.
21 | *
22 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
23 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
24 | * of the code.
25 | */
26 | #ifndef KERNEL_MAP_HPP
27 | #define KERNEL_MAP_HPP
28 |
29 | #include "types.hpp"
30 |
31 | #include
32 | #include
33 | #include
34 |
35 | namespace minkowski {
36 |
37 | /*
38 | * Kernel map specific types
39 | */
40 | using cpu_in_map = default_types::index_vector_type;
41 | using cpu_out_map = default_types::index_vector_type;
42 |
43 | // Input index to output index mapping for each spatial kernel
44 | using cpu_in_maps = std::vector;
45 | using cpu_out_maps = std::vector;
46 | struct cpu_kernel_map : std::pair {
47 | using index_type = default_types::index_type;
48 | using index_pair =
49 | std::pair;
50 |
51 | cpu_kernel_map() : std::pair() {}
52 | cpu_kernel_map(std::pair const &other)
53 | : std::pair(other) {}
54 |
55 | // origin map initialization.
56 | cpu_kernel_map(std::vector &in_out,
57 | std::vector const
58 | &unique_batch_indicies) {
59 | auto comp = [](std::pair const &l,
60 | std::pair const &r) {
61 | return l.second < r.second;
62 | };
63 | std::sort(in_out.begin(), in_out.end(), comp);
64 |
65 | auto const kernel_volume = unique_batch_indicies.size();
66 | this->first.resize(kernel_volume);
67 | this->second.resize(kernel_volume);
68 |
69 | for (index_type k = 0; k < unique_batch_indicies.size(); ++k) {
70 | auto const lb = std::lower_bound(in_out.begin(), in_out.end(),
71 | index_pair{0, k}, comp);
72 | auto const ub = std::upper_bound(in_out.begin(), in_out.end(),
73 | index_pair{0, k}, comp);
74 | auto const curr_size = ub - lb;
75 | default_types::index_type start_index = lb - in_out.begin();
76 | LOG_DEBUG("batch row_index:", k, "curr_size:", curr_size,
77 | "start_index:", start_index);
78 | // resize
79 | auto &in_map = this->first[k];
80 | auto &out_map = this->second[k];
81 | in_map.resize(curr_size);
82 | out_map.resize(curr_size);
83 | // copy
84 | for (uint32_t i = 0; i < curr_size; ++i) {
85 | auto const &curr_pair = in_out[i + start_index];
86 | in_map[i] = curr_pair.first;
87 | out_map[i] = curr_pair.second;
88 | }
89 | }
90 | }
91 |
92 | friend std::ostream &operator<<(std::ostream &out,
93 | cpu_kernel_map const &kernel_map) {
94 | uint32_t map_size = 0;
95 | for (auto const &v : kernel_map.first) {
96 | map_size += v.size();
97 | }
98 | out << "cpu_kernel_map: number of unique maps:" << kernel_map.first.size()
99 | << ", kernel map size:" << map_size;
100 | return out;
101 | }
102 | };
103 |
104 | using cpu_kernel_map_reference = std::pair;
105 |
106 | } // namespace minkowski
107 |
108 | #endif
109 |
--------------------------------------------------------------------------------
/src/math_functions.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020 NVIDIA Corporation.
3 | * Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in
13 | * all copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 | * IN THE SOFTWARE.
22 | *
23 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
24 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
25 | * of the code.
26 | */
27 | #ifndef MATH_FUNCTIONS_HPP
28 | #define MATH_FUNCTIONS_HPP
29 |
30 | #include "mkl_alternate.hpp"
31 |
32 | namespace minkowski {
33 |
34 | template
35 | void cpu_gemm(const CBLAS_ORDER Layout, const CBLAS_TRANSPOSE TransA,
36 | const CBLAS_TRANSPOSE TransB, const int M, const int N,
37 | const int K, const Dtype alpha, const Dtype *A, const Dtype *B,
38 | const Dtype beta, Dtype *C);
39 |
40 | template
41 | void cpu_add(const int N, const Dtype *a, const Dtype *b, Dtype *y);
42 |
43 | template
44 | void cpu_mul(const int N, const Dtype *a, const Dtype *b, Dtype *y);
45 |
46 | template
47 | void cpu_div(const int N, const Dtype *a, const Dtype *b, Dtype *y);
48 |
49 | template
50 | void cpu_axpy(const int N, const Dtype alpha, const Dtype *X, Dtype *Y);
51 |
52 | } // end namespace minkowski
53 |
54 | #endif // MATH_FUNCTIONS
55 |
--------------------------------------------------------------------------------
/src/math_functions_cpu.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | * copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 | * IN THE SOFTWARE.
20 | *
21 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | * of the code.
24 | */
25 | #include "math_functions.hpp"
26 |
27 | namespace minkowski {
28 |
29 | template <>
30 | void cpu_gemm(const CBLAS_ORDER Layout, const CBLAS_TRANSPOSE TransA,
31 | const CBLAS_TRANSPOSE TransB, const int M, const int N,
32 | const int K, const float alpha, const float *A,
33 | const float *B, const float beta, float *C) {
34 | int lda, ldb, ldc;
35 | if (Layout == CblasRowMajor) {
36 | lda = (TransA == CblasNoTrans) ? K : M;
37 | ldb = (TransB == CblasNoTrans) ? N : K;
38 | ldc = N;
39 | } else {
40 | lda = (TransA == CblasNoTrans) ? M : K;
41 | ldb = (TransB == CblasNoTrans) ? K : N;
42 | ldc = M;
43 | }
44 | cblas_sgemm(Layout, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C,
45 | ldc);
46 | }
47 |
48 | template <>
49 | void cpu_gemm(const CBLAS_ORDER Layout, const CBLAS_TRANSPOSE TransA,
50 | const CBLAS_TRANSPOSE TransB, const int M, const int N,
51 | const int K, const double alpha, const double *A,
52 | const double *B, const double beta, double *C) {
53 | int lda, ldb, ldc;
54 | if (Layout == CblasRowMajor) {
55 | lda = (TransA == CblasNoTrans) ? K : M;
56 | ldb = (TransB == CblasNoTrans) ? N : K;
57 | ldc = N;
58 | } else {
59 | lda = (TransA == CblasNoTrans) ? M : K;
60 | ldb = (TransB == CblasNoTrans) ? K : N;
61 | ldc = M;
62 | }
63 | cblas_dgemm(Layout, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C,
64 | ldc);
65 | }
66 |
67 | template <>
68 | void cpu_add(const int n, const float *a, const float *b, float *y) {
69 | vsAdd(n, a, b, y);
70 | }
71 |
72 | template <>
73 | void cpu_add(const int n, const double *a, const double *b, double *y) {
74 | vdAdd(n, a, b, y);
75 | }
76 |
77 | template <>
78 | void cpu_mul(const int n, const float *a, const float *b, float *y) {
79 | vsMul(n, a, b, y);
80 | }
81 |
82 | template <>
83 | void cpu_mul(const int n, const double *a, const double *b, double *y) {
84 | vdMul(n, a, b, y);
85 | }
86 |
87 | template <>
88 | void cpu_div(const int n, const float *a, const float *b, float *y) {
89 | vsDiv(n, a, b, y);
90 | }
91 |
92 | template <>
93 | void cpu_div(const int n, const double *a, const double *b, double *y) {
94 | vdMul(n, a, b, y);
95 | }
96 |
97 | template <>
98 | void cpu_axpy(const int N, const float alpha, const float *X, float *Y) {
99 | cblas_saxpy(N, alpha, X, 1, Y, 1);
100 | }
101 |
102 | template <>
103 | void cpu_axpy(const int N, const double alpha, const double *X,
104 | double *Y) {
105 | cblas_daxpy(N, alpha, X, 1, Y, 1);
106 | }
107 |
108 | } // end namespace minkowski
109 |
--------------------------------------------------------------------------------
/src/mkl_alternate.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | * this software and associated documentation files (the "Software"), to deal in
5 | * the Software without restriction, including without limitation the rights to
6 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | * of the Software, and to permit persons to whom the Software is furnished to do
8 | * so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in all
11 | * copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | * SOFTWARE.
20 | *
21 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | * of the code.
24 | */
25 | #ifndef MKL_ALTERNATE_H_
26 | #define MKL_ALTERNATE_H_
27 |
28 | #ifdef USE_MKL
29 |
30 | #include
31 |
32 | #else // If use MKL, simply include the MKL header
33 |
34 | extern "C" {
35 | #include
36 | }
37 | #include
38 |
39 |
40 | // A simple way to define the vsl binary functions. The operation should
41 | // be in the form e.g. y[i] = a[i] + b[i]
42 | #define DEFINE_VSL_BINARY_FUNC(name, operation) \
43 | template \
44 | void v##name(const int n, const Dtype* a, const Dtype* b, Dtype* y) { \
45 | for (int i = 0; i < n; ++i) { operation; } \
46 | } \
47 | inline void vs##name( \
48 | const int n, const float* a, const float* b, float* y) { \
49 | v##name(n, a, b, y); \
50 | } \
51 | inline void vd##name( \
52 | const int n, const double* a, const double* b, double* y) { \
53 | v##name(n, a, b, y); \
54 | }
55 |
56 | DEFINE_VSL_BINARY_FUNC(Add, y[i] = a[i] + b[i])
57 | DEFINE_VSL_BINARY_FUNC(Sub, y[i] = a[i] - b[i])
58 | DEFINE_VSL_BINARY_FUNC(Mul, y[i] = a[i] * b[i])
59 | DEFINE_VSL_BINARY_FUNC(Div, y[i] = a[i] / b[i])
60 |
61 | #endif // USE_MKL
62 | #endif // MKL_ALTERNATE_H_
63 |
--------------------------------------------------------------------------------
/src/pooling_avg_kernel.cuh:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020 NVIDIA Corporation.
3 | * Copyright (c) 2018-2020 Chris Choy (chrischoy@ai.stanford.edu).
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in
13 | * all copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 | * IN THE SOFTWARE.
22 | *
23 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
24 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
25 | * of the code.
26 | */
27 | #ifndef POOLING_AVG_CUH
28 | #define POOLING_AVG_CUH
29 |
30 | #include
31 | #include
32 |
33 | #include "gpu.cuh"
34 | #include "kernel_map.cuh"
35 | #include "math_functions.cuh"
36 | #include "types.hpp"
37 |
38 | namespace minkowski {
39 |
40 | template
41 | void NonzeroAvgPoolingForwardKernelGPU(
42 | Dtype const *d_in_feat, //
43 | default_types::size_type const in_nrows, //
44 | Dtype *d_out_feat, //
45 | default_types::size_type const out_nrows, //
46 | Dtype *d_num_nonzero, //
47 | default_types::size_type const nchannel, //
48 | gpu_kernel_map const &kernel_map, //
49 | bool const use_avg,
50 | ByteAllocator &allocator, //
51 | cusparseHandle_t cushandle, cudaStream_t stream);
52 |
53 | template
54 | void NonzeroAvgPoolingBackwardKernelGPU(
55 | Dtype *d_grad_in_feat, //
56 | default_types::size_type const in_nrows, //
57 | Dtype const *d_grad_out_feat, //
58 | default_types::size_type const out_nrows, //
59 | Dtype const *d_num_nonzero, //
60 | default_types::size_type const nchannel, //
61 | gpu_kernel_map const &kernel_map, bool const use_avg,
62 | cudaStream_t stream);
63 |
64 | } // end namespace minkowski
65 |
66 | #endif // POOLING_AVG_CUH
67 |
--------------------------------------------------------------------------------
/src/pooling_max_kernel.cuh:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | * copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 | * IN THE SOFTWARE.
20 | *
21 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | * of the code.
24 | */
25 | #ifndef POOLING_MAX_CUH
26 | #define POOLING_MAX_CUH
27 |
28 | #include
29 | #include
30 |
31 | #include "allocators.cuh"
32 | #include "gpu.cuh"
33 | #include "kernel_map.cuh"
34 | #include "math_functions.cuh"
35 | #include "types.hpp"
36 |
37 | namespace minkowski {
38 |
39 | template
40 | void max_pool_forward_pointer_kernel_gpu(
41 | MapItype *d_in_map, // this will be sorted
42 | MapItype *d_out_map, // this will be sorted
43 | size_t const nmap, // map size
44 | Dtype const *d_in_feat, //
45 | Dtype *d_out_feat, //
46 | size_t const out_nrows, //
47 | size_t const nchannel, //
48 | MaskItype *d_max_index, //
49 | bool const is_sorted //
50 | );
51 |
52 | template
53 | void MaxPoolingForwardKernelGPU(
54 | const Dtype *d_in_feat, Dtype *d_out_feat, size_t const out_nrows,
55 | int *d_max_index, size_t const nchannel,
56 | gpu_kernel_map const &kernel_map,
57 | ByteAllocator &allocator, cudaStream_t stream);
58 |
59 | template
60 | void MaxPoolingBackwardKernelGPU(Dtype *d_grad_in_feat, size_t const in_nrows,
61 | const Dtype *d_grad_out_feat,
62 | size_t const out_nrows,
63 | const MaskItype *d_max_index,
64 | size_t const nchannel);
65 |
66 | } // end namespace minkowski
67 |
68 | #endif // end POOLING_MAX_CUH
69 |
--------------------------------------------------------------------------------
/src/pruning.hpp:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | * copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 | * IN THE SOFTWARE.
20 | *
21 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | * of the code.
24 | */
25 | #ifndef CPU_PRUNING
26 | #define CPU_PRUNING
27 |
28 | #include "types.hpp"
29 |
30 | namespace minkowski {
31 |
32 | template
33 | void PruningForwardKernelCPU(const Dtype *p_in_feat, Dtype *p_out_feat,
34 | int const nchannel, const cpu_in_maps &in_maps,
35 | const cpu_out_maps &out_maps) {
36 | const Dtype *p_curr_in;
37 | Dtype *p_curr_out;
38 | auto const &in_map = in_maps[0];
39 | auto const &out_map = out_maps[0];
40 | // Iterate through each spatial kernel out of filter_volume spatial kernels
41 | for (uint32_t row = 0; row < in_map.size(); row++) {
42 | // Define current pointers
43 | p_curr_in = p_in_feat + in_map[row] * nchannel;
44 | p_curr_out = p_out_feat + out_map[row] * nchannel;
45 | std::memcpy(p_curr_out, p_curr_in, nchannel * sizeof(Dtype));
46 | }
47 | }
48 |
49 | template
50 | void PruningBackwardKernelCPU(Dtype *p_grad_in_feat,
51 | const Dtype *p_grad_out_feat, int const nchannel,
52 | const cpu_in_maps &in_maps,
53 | const cpu_out_maps &out_maps) {
54 | Dtype *p_curr_grad_in;
55 | const Dtype *p_curr_grad_out;
56 | auto const &in_map = in_maps[0];
57 | auto const &out_map = out_maps[0];
58 |
59 | for (uint32_t row = 0; row < in_map.size(); row++) {
60 | // Define current pointers
61 | p_curr_grad_in = p_grad_in_feat + in_map[row] * nchannel;
62 | p_curr_grad_out = p_grad_out_feat + out_map[row] * nchannel;
63 | std::memcpy(p_curr_grad_in, p_curr_grad_out, nchannel * sizeof(Dtype));
64 | }
65 | }
66 |
67 | } // end namespace minkowski
68 |
69 | #endif // CPU_PRUNING
70 |
--------------------------------------------------------------------------------
/src/sharedmem.cuh:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 1993-2014 NVIDIA Corporation. All rights reserved.
3 | *
4 | * Please refer to the NVIDIA end user license agreement (EULA) associated
5 | * with this source code for terms and conditions that govern your use of
6 | * this software. Any use, reproduction, disclosure, or distribution of
7 | * this software and related documentation outside the terms of the EULA
8 | * is strictly prohibited.
9 | *
10 | */
11 |
12 | #ifndef _SHAREDMEM_H_
13 | #define _SHAREDMEM_H_
14 |
15 | //****************************************************************************
16 | // Because dynamically sized shared memory arrays are declared "extern",
17 | // we can't templatize them directly. To get around this, we declare a
18 | // simple wrapper struct that will declare the extern array with a different
19 | // name depending on the type. This avoids compiler errors about duplicate
20 | // definitions.
21 | //
22 | // To use dynamically allocated shared memory in a templatized __global__ or
23 | // __device__ function, just replace code like this:
24 | //
25 | //
26 | // template
27 | // __global__ void
28 | // foo( T* g_idata, T* g_odata)
29 | // {
30 | // // Shared mem size is determined by the host app at run time
31 | // extern __shared__ T sdata[];
32 | // ...
33 | // doStuff(sdata);
34 | // ...
35 | // }
36 | //
37 | // With this
38 | // template
39 | // __global__ void
40 | // foo( T* g_idata, T* g_odata)
41 | // {
42 | // // Shared mem size is determined by the host app at run time
43 | // SharedMemory smem;
44 | // T* sdata = smem.getPointer();
45 | // ...
46 | // doStuff(sdata);
47 | // ...
48 | // }
49 | //****************************************************************************
50 |
51 | // This is the un-specialized struct. Note that we prevent instantiation of
52 | // this struct by putting an undefined symbol in the function body so it won't
53 | // compile.
54 | template struct SharedMemory {
55 | // Ensure that we won't compile any un-specialized types
56 | __device__ T *getPointer() {
57 | extern __device__ void error(void);
58 | error();
59 | return NULL;
60 | }
61 | };
62 |
63 | // Following are the specializations for the following types.
64 | // int, uint, char, uchar, short, ushort, long, ulong, bool, float, and double
65 | // One could also specialize it for user-defined types.
66 |
67 | template <> struct SharedMemory {
68 | __device__ int *getPointer() {
69 | extern __shared__ int s_int[];
70 | return s_int;
71 | }
72 | };
73 |
74 | template <> struct SharedMemory {
75 | __device__ unsigned int *getPointer() {
76 | extern __shared__ unsigned int s_uint[];
77 | return s_uint;
78 | }
79 | };
80 |
81 | template <> struct SharedMemory {
82 | __device__ char *getPointer() {
83 | extern __shared__ char s_char[];
84 | return s_char;
85 | }
86 | };
87 |
88 | template <> struct SharedMemory {
89 | __device__ unsigned char *getPointer() {
90 | extern __shared__ unsigned char s_uchar[];
91 | return s_uchar;
92 | }
93 | };
94 |
95 | template <> struct SharedMemory {
96 | __device__ short *getPointer() {
97 | extern __shared__ short s_short[];
98 | return s_short;
99 | }
100 | };
101 |
102 | template <> struct SharedMemory {
103 | __device__ unsigned short *getPointer() {
104 | extern __shared__ unsigned short s_ushort[];
105 | return s_ushort;
106 | }
107 | };
108 |
109 | template <> struct SharedMemory {
110 | __device__ long *getPointer() {
111 | extern __shared__ long s_long[];
112 | return s_long;
113 | }
114 | };
115 |
116 | template <> struct SharedMemory {
117 | __device__ unsigned long *getPointer() {
118 | extern __shared__ unsigned long s_ulong[];
119 | return s_ulong;
120 | }
121 | };
122 |
123 | template <> struct SharedMemory {
124 | __device__ bool *getPointer() {
125 | extern __shared__ bool s_bool[];
126 | return s_bool;
127 | }
128 | };
129 |
130 | template <> struct SharedMemory {
131 | __device__ float *getPointer() {
132 | extern __shared__ float s_float[];
133 | return s_float;
134 | }
135 | };
136 |
137 | template <> struct SharedMemory {
138 | __device__ double *getPointer() {
139 | extern __shared__ double s_double[];
140 | return s_double;
141 | }
142 | };
143 |
144 | #endif //_SHAREDMEM_H_
145 |
--------------------------------------------------------------------------------
/src/spmm.cuh:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020 NVIDIA Corporation.
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
23 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
24 | * of the code.
25 | */
26 | #ifndef SPMM_CUH
27 | #define SPMM_CUH
28 | #include "gpu.cuh"
29 |
30 | #include
31 |
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 |
38 | namespace minkowski {
39 |
40 | template
41 | torch::Tensor coo_spmm(torch::Tensor const &rows, torch::Tensor const &cols,
42 | torch::Tensor const &vals, int64_t const dim_i,
43 | int64_t const dim_j, torch::Tensor const &mat2,
44 | int64_t const spmm_algorithm_id, bool const is_sorted);
45 |
46 | template
47 | std::vector // output, sorted rows, sorted cols, sorted vals.
48 | coo_spmm_average(torch::Tensor const &rows, torch::Tensor const &cols,
49 | int64_t const dim_i, int64_t const dim_j,
50 | torch::Tensor const &mat2, int64_t const spmm_algorithm_id);
51 | } // namespace minkowski
52 | #endif
53 |
--------------------------------------------------------------------------------
/tests/cpp/README.md:
--------------------------------------------------------------------------------
1 | # C++ Backend Unit Tests
2 |
3 | ## Installation
4 |
5 | ```
6 | rm -rf build; CXX=g++; python setup.py install
7 | ```
8 |
9 | ## Individual Test
10 |
11 | ```
12 | python -m unittest
13 | python -m unittest --nodebug # to remove deub flags
14 | ```
15 |
16 | e.g.
17 |
18 | ```
19 | python -m unittest coordinate_map_key_test
20 | ```
21 |
--------------------------------------------------------------------------------
/tests/cpp/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NVIDIA/MinkowskiEngine/02fc608bea4c0549b0a7b00ca1bf15dee4a0b228/tests/cpp/__init__.py
--------------------------------------------------------------------------------
/tests/cpp/convolution_cpu.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import unittest
3 | import time
4 |
5 | import torch
6 | import MinkowskiEngineTest._C as _C
7 |
8 | from utils import load_file, batched_coordinates
9 |
10 |
11 | class ConvolutionTestCase(unittest.TestCase):
12 | def test_stride(self):
13 | coordinates = torch.IntTensor([[0, 1], [1, 2], [2, 3], [2, 3]])
14 | key, manager, map_inverse_map = _C.coordinate_map_manager_test(coordinates, "")
15 | unique_map, inverse_map = map_inverse_map
16 | stride = [2]
17 | key = _C.coordinate_map_manager_stride(manager, key, stride)
18 | print(key)
19 |
20 | def test_pcd(self):
21 | coords, colors, pcd = load_file("1.ply")
22 | kernel_size = torch.IntTensor([3, 3, 3])
23 | for batch_size in [1, 5, 10, 20, 40]:
24 | for voxel_size in [0.05, 0.035, 0.02]:
25 | min_time = 100000
26 | dcoords = torch.from_numpy(np.floor(coords / voxel_size)).int()
27 | bcoords = batched_coordinates([dcoords for i in range(batch_size)])
28 | for i in range(10):
29 | kernel_map, num, t = MinkowskiEngineTest._C.kernel_map_test(
30 | bcoords, bcoords, kernel_size
31 | )
32 | min_time = min(t, min_time)
33 |
34 | num_kernels = np.sum([len(a) for a in kernel_map[0]])
35 | print(f"{batch_size}\t{voxel_size}\t{num}\t{num_kernels}\t{min_time}")
36 |
--------------------------------------------------------------------------------
/tests/cpp/coordinate_map_key_test.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2020 NVIDIA CORPORATION.
2 | * Copyright (c) 2018-2020 Chris Choy (chrischoy@ai.stanford.edu)
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 | * IN THE SOFTWARE.
21 | *
22 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
23 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
24 | * of the code.
25 | */
26 | #include "coordinate_map_key.hpp"
27 |
28 | #include
29 | #include
30 |
31 | namespace minkowski {
32 |
33 | void coordinate_map_key_test() {
34 | // Check basic type compilation
35 | CoordinateMapKey key{3};
36 | CoordinateMapKey key2{default_types::stride_type{2, 3, 4}};
37 | }
38 |
39 | py::object coordinate_map_key_return(default_types::stride_type tensor_stride,
40 | std::string string_id) {
41 | return py::cast(new CoordinateMapKey(tensor_stride, string_id));
42 | }
43 |
44 | void coordinate_map_key_update(CoordinateMapKey *map_key,
45 | default_types::stride_type tensor_stride,
46 | std::string string_id) {
47 | map_key->set_key(tensor_stride, string_id);
48 | }
49 |
50 | } // namespace minkowski
51 |
52 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
53 | py::class_(m, "CoordinateMapKey")
54 | .def(py::init())
55 | .def(py::init())
56 | .def("__repr__", &minkowski::CoordinateMapKey::to_string)
57 | .def("get_coordinate_size",
58 | &minkowski::CoordinateMapKey::get_coordinate_size)
59 | .def("get_key", &minkowski::CoordinateMapKey::get_key)
60 | .def("set_key", (void (minkowski::CoordinateMapKey::*)(
61 | minkowski::default_types::stride_type, std::string)) &
62 | minkowski::CoordinateMapKey::set_key)
63 | .def("get_tensor_stride",
64 | &minkowski::CoordinateMapKey::get_tensor_stride);
65 |
66 | m.def("coordinate_map_key_return", &minkowski::coordinate_map_key_return,
67 | "Minkowski Engine coordinate map key return test");
68 |
69 | m.def("coordinate_map_key_test", &minkowski::coordinate_map_key_test,
70 | "Minkowski Engine coordinate map key test");
71 |
72 | m.def("coordinate_map_key_update", &minkowski::coordinate_map_key_update,
73 | "Minkowski Engine coordinate map key update test");
74 | }
75 |
--------------------------------------------------------------------------------
/tests/cpp/coordinate_map_key_test.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | import torch
3 | import MinkowskiEngineTest._C
4 |
5 |
6 | class CoordinateMapKeyTestCase(unittest.TestCase):
7 | def test(self):
8 | MinkowskiEngineTest._C.coordinate_map_key_test()
9 | key = MinkowskiEngineTest._C.CoordinateMapKey([3, 4, 5], "")
10 | print(key.__repr__())
11 | self.assertEqual([3, 4, 5], key.get_tensor_stride())
12 | self.assertEqual(4, key.get_coordinate_size())
13 | self.assertEqual(([3, 4, 5], ''), key.get_key())
14 |
15 | def test(self):
16 | MinkowskiEngineTest._C.coordinate_map_key_test()
17 | key = MinkowskiEngineTest._C.CoordinateMapKey(3)
18 | print(key.__repr__())
19 | MinkowskiEngineTest._C.coordinate_map_key_update(key, [2, 3], "test")
20 | print(key.__repr__())
21 | self.assertEqual(([2, 3], "test"), key.get_key())
22 | with self.assertRaises(RuntimeError):
23 | MinkowskiEngineTest._C.coordinate_map_key_update(key, [2, 3, 4], "")
24 |
--------------------------------------------------------------------------------
/tests/cpp/coordinate_map_manager_cpu_test.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | import torch
3 | import MinkowskiEngineTest._C as _C
4 |
5 |
6 | class CoordinateMapManagerTestCase(unittest.TestCase):
7 | def test(self):
8 | coordinates = torch.IntTensor([[0, 1], [1, 2], [2, 3], [2, 3]])
9 | key, manager, map_inverse_map = _C.coordinate_map_manager_test(coordinates, "")
10 | unique_map, inverse_map = map_inverse_map
11 | self.assertTrue(
12 | torch.all(coordinates[unique_map.long()][inverse_map.long()] == coordinates)
13 | )
14 |
15 | def test_stride(self):
16 | coordinates = torch.IntTensor([[0, 1], [1, 2], [2, 3], [2, 3]])
17 | key, manager, map_inverse_map = _C.coordinate_map_manager_test(coordinates, "")
18 | unique_map, inverse_map = map_inverse_map
19 | stride = [2]
20 | key = _C.coordinate_map_manager_stride(manager, key, stride)
21 | print(key)
22 |
23 | def test_kernel_map(self):
24 | coordinates = torch.IntTensor([[0, 1], [0, 2], [1, 2], [1, 3]])
25 | manager = _C.CoordinateMapManager()
26 | key, (unique_map, inverse_map) = manager.insert_and_map(coordinates, [1], "1")
27 | key2, (unique_map2, inverse_map2) = manager.insert_and_map(
28 | coordinates, [1], "2"
29 | )
30 | print(key, key2)
31 | self.assertTrue(
32 | torch.all(coordinates[unique_map.long()][inverse_map.long()] == coordinates)
33 | )
34 | in_maps, out_maps = _C.coordinate_map_manager_kernel_map(
35 | manager, key, key2, [3]
36 | )
37 |
38 | print(in_maps)
39 | print(out_maps)
40 |
--------------------------------------------------------------------------------
/tests/cpp/coordinate_map_manager_gpu_test.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | import torch
3 | import MinkowskiEngineTest._C as _C
4 |
5 |
6 | class CoordinateMapManagerTestCase(unittest.TestCase):
7 | def test(self):
8 | coordinates = torch.IntTensor([[0, 1], [1, 2], [2, 3], [2, 3]]).to(0)
9 | key, manager, map_inverse_map = _C.coordinate_map_manager_test(coordinates, "")
10 | unique_map, inverse_map = map_inverse_map
11 | self.assertTrue(
12 | torch.all(coordinates[unique_map.long()][inverse_map.long()] == coordinates)
13 | )
14 |
15 | def test_stride(self):
16 | coordinates = torch.IntTensor([[0, 1], [1, 2], [2, 3], [2, 3]]).to(0)
17 | key, manager, map_inverse_map = _C.coordinate_map_manager_test(coordinates, "")
18 | unique_map, inverse_map = map_inverse_map
19 | stride = [2]
20 | key = _C.coordinate_map_manager_stride(manager, key, stride)
21 | print(key)
22 |
23 | def test_collision(self):
24 | coordinates = torch.IntTensor([[0, 1], [0, 1], [1, 2], [1, 2]]).to(0)
25 | manager = _C.CoordinateMapManager()
26 | key, (unique_map, inverse_map) = manager.insert_and_map(coordinates, [1], "1")
27 | key2, (unique_map2, inverse_map2) = manager.insert_and_map(
28 | coordinates, [1], "2"
29 | )
30 | print(unique_map, inverse_map)
31 | in_maps, out_maps = _C.coordinate_map_manager_kernel_map(
32 | manager, key, key2, [3]
33 | )
34 |
35 | print(in_maps)
36 | print(out_maps)
37 |
38 | def test_kernel_map(self):
39 | coordinates = torch.IntTensor([[0, 1], [0, 2], [1, 2], [1, 3]]).to(0)
40 | manager = _C.CoordinateMapManager()
41 | key, (unique_map, inverse_map) = manager.insert_and_map(coordinates, [1], "1")
42 | key2, (unique_map2, inverse_map2) = manager.insert_and_map(
43 | coordinates, [1], "2"
44 | )
45 | print(key, key2)
46 | self.assertTrue(
47 | torch.all(coordinates[unique_map.long()][inverse_map.long()] == coordinates)
48 | )
49 | in_maps, out_maps = _C.coordinate_map_manager_kernel_map(
50 | manager, key, key2, [3]
51 | )
52 |
53 | print(in_maps)
54 | print(out_maps)
55 |
--------------------------------------------------------------------------------
/tests/cpp/coordinate_test.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2020 NVIDIA CORPORATION.
2 | * Copyright (c) 2018-2020 Chris Choy (chrischoy@ai.stanford.edu)
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 | * IN THE SOFTWARE.
21 | *
22 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
23 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
24 | * of the code.
25 | */
26 | #include "coordinate.hpp"
27 | #include "types.hpp"
28 |
29 | #include
30 | #include
31 | #include
32 |
33 | namespace minkowski {
34 |
35 | using coordinate_type = int32_t;
36 |
37 | uint32_t coordinate_test(const torch::Tensor &coordinates) {
38 | // Create TensorArgs. These record the names and positions of each tensor as a
39 | // parameter.
40 | torch::TensorArg arg_coordinates(coordinates, "coordinates", 0);
41 |
42 | torch::CheckedFrom c = "coordinate_test";
43 | torch::checkContiguous(c, arg_coordinates);
44 | // must match coordinate_type
45 | torch::checkScalarType(c, arg_coordinates, torch::kInt);
46 | torch::checkBackend(c, arg_coordinates.tensor, torch::Backend::CPU);
47 | torch::checkDim(c, arg_coordinates, 2);
48 |
49 | auto const N = (uint32_t)coordinates.size(0);
50 | auto const D = (uint32_t)coordinates.size(1);
51 |
52 | using map_type =
53 | std::unordered_map, default_types::index_type,
54 | detail::coordinate_murmur3,
55 | detail::coordinate_equal_to>;
56 |
57 | map_type map = map_type{N, detail::coordinate_murmur3{D},
58 | detail::coordinate_equal_to{D}};
59 | coordinate_type const * ptr = coordinates.data_ptr();
60 | for (default_types::index_type i = 0; i < N; i++) {
61 | map[coordinate{ptr + D * i}] = i;
62 | }
63 |
64 | return map.size();
65 | }
66 |
67 | } // namespace minkowski
68 |
69 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
70 | m.def("coordinate_test", &minkowski::coordinate_test,
71 | "Minkowski Engine coordinate test");
72 | }
73 |
--------------------------------------------------------------------------------
/tests/cpp/coordinate_test.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | import torch
3 | import MinkowskiEngineTest._C
4 |
5 |
6 | class CoordinateTestCase(unittest.TestCase):
7 | def test_check(self):
8 | coordinates = torch.FloatTensor([2, 3])
9 | with self.assertRaises(RuntimeError):
10 | MinkowskiEngineTest._C.coordinate_test(coordinates)
11 |
12 | coordinates = torch.IntTensor([2, 3])
13 | with self.assertRaises(RuntimeError):
14 | MinkowskiEngineTest._C.coordinate_test(coordinates)
15 |
16 | def test(self):
17 | coordinates = torch.IntTensor([[0, 1], [1, 2], [2, 3], [2, 3]])
18 | self.assertEqual(MinkowskiEngineTest._C.coordinate_test(coordinates), 3)
19 |
--------------------------------------------------------------------------------
/tests/cpp/test_all.sh:
--------------------------------------------------------------------------------
1 | export CXX=g++-7;
2 |
3 | rm -rf build; python setup.py install --test=coordinate
4 | python -m unittest coordinate_test
5 |
6 | rm -rf build; python setup.py install --test=coordinate_map_key
7 | python -m unittest coordinate_map_key_test
8 |
9 | rm -rf build; python setup.py install --test=coordinate_map_cpu
10 | python -m unittest coordinate_map_cpu_test
11 |
12 | rm -rf build; python setup.py install --test=coordinate_map_gpu
13 | python -m unittest coordinate_map_gpu_test
14 |
15 | rm -rf build; python setup.py install --test=region_cpu
16 | python -m unittest kernel_region_cpu_test
17 |
--------------------------------------------------------------------------------
/tests/cpp/type_test.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2020 NVIDIA Corporation.
2 | *
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy
4 | * of this software and associated documentation files (the "Software"), to deal
5 | * in the Software without restriction, including without limitation the rights
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | * copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in
11 | * all copies or substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 | * IN THE SOFTWARE.
20 | *
21 | * Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | * Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | * of the code.
24 | */
25 | #include "types.hpp"
26 |
27 | #include
28 |
29 | namespace minkowski {
30 |
31 | void type_test() {
32 | // Check basic type compilation
33 | constexpr default_types::tensor_order_type D = 3;
34 | constexpr default_types::dcoordinate_type a = 3;
35 |
36 | const cpuInMap in_map = std::vector{3, 4, 5};
37 | const cpuOutMap out_map = std::vector{3, 4, 5};
38 | const cpuInMaps in_maps = {in_map};
39 | const cpuOutMaps out_maps = {out_map};
40 | }
41 |
42 | } // namespace minkowski
43 |
44 | PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
45 | m.def("type_test", &minkowski::type_test, "Minkowski Engine type test");
46 | }
47 |
--------------------------------------------------------------------------------
/tests/cpp/type_test.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | import torch
3 | import MinkowskiEngineTest._C
4 |
5 |
6 | class TypeTestCase(unittest.TestCase):
7 |
8 | def test(self):
9 | MinkowskiEngineTest._C.type_test()
10 | self.assertErtTrue(True)
11 |
--------------------------------------------------------------------------------
/tests/cpp/utils.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2020 NVIDIA CORPORATION.
2 | # Copyright (c) 2018-2020 Chris Choy (chrischoy@ai.stanford.edu).
3 | #
4 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
5 | # this software and associated documentation files (the "Software"), to deal in
6 | # the Software without restriction, including without limitation the rights to
7 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8 | # of the Software, and to permit persons to whom the Software is furnished to do
9 | # so, subject to the following conditions:
10 | #
11 | # The above copyright notice and this permission notice shall be included in all
12 | # copies or substantial portions of the Software.
13 | #
14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | # SOFTWARE.
21 | #
22 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
23 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
24 | # of the code.
25 |
26 | import os
27 | import numpy as np
28 | import collections
29 | from urllib.request import urlretrieve
30 |
31 | import torch
32 |
33 | try:
34 | import open3d as o3d
35 | except ImportError:
36 | raise ImportError("Please install open3d with `pip install open3d`.")
37 |
38 | if not os.path.isfile("1.ply"):
39 | urlretrieve("https://bit.ly/3c2iLhg", "1.ply")
40 |
41 |
42 | def load_file(file_name):
43 | pcd = o3d.io.read_point_cloud(file_name)
44 | coords = np.array(pcd.points)
45 | colors = np.array(pcd.colors)
46 | return coords, colors, pcd
47 |
48 |
49 | def batched_coordinates(coords, dtype=torch.int32, device=None):
50 | r"""Create a `ME.SparseTensor` coordinates from a sequence of coordinates
51 |
52 | Given a list of either numpy or pytorch tensor coordinates, return the
53 | batched coordinates suitable for `ME.SparseTensor`.
54 |
55 | Args:
56 | :attr:`coords` (a sequence of `torch.Tensor` or `numpy.ndarray`): a
57 | list of coordinates.
58 |
59 | :attr:`dtype`: torch data type of the return tensor. torch.int32 by default.
60 |
61 | Returns:
62 | :attr:`batched_coordindates` (`torch.Tensor`): a batched coordinates.
63 |
64 | .. warning::
65 |
66 | From v0.4, the batch index will be prepended before all coordinates.
67 |
68 | """
69 | assert isinstance(
70 | coords, collections.abc.Sequence
71 | ), "The coordinates must be a sequence."
72 | assert np.array(
73 | [cs.ndim == 2 for cs in coords]
74 | ).all(), "All coordinates must be in a 2D array."
75 | D = np.unique(np.array([cs.shape[1] for cs in coords]))
76 | assert len(D) == 1, f"Dimension of the array mismatch. All dimensions: {D}"
77 | D = D[0]
78 | if device is None:
79 | if isinstance(coords, torch.Tensor):
80 | device = coords[0].device
81 | else:
82 | device = "cpu"
83 | assert dtype in [
84 | torch.int32,
85 | torch.float32,
86 | ], "Only torch.int32, torch.float32 supported for coordinates."
87 |
88 | # Create a batched coordinates
89 | N = np.array([len(cs) for cs in coords]).sum()
90 | bcoords = torch.zeros((N, D + 1), dtype=dtype, device=device) # uninitialized
91 |
92 | s = 0
93 | for b, cs in enumerate(coords):
94 | if dtype == torch.int32:
95 | if isinstance(cs, np.ndarray):
96 | cs = torch.from_numpy(np.floor(cs))
97 | elif not (
98 | isinstance(cs, torch.IntTensor) or isinstance(cs, torch.LongTensor)
99 | ):
100 | cs = cs.floor()
101 |
102 | cs = cs.int()
103 | else:
104 | if isinstance(cs, np.ndarray):
105 | cs = torch.from_numpy(cs)
106 |
107 | cn = len(cs)
108 | # BATCH_FIRST:
109 | bcoords[s : s + cn, 1:] = cs
110 | bcoords[s : s + cn, 0] = b
111 | s += cn
112 | return bcoords
--------------------------------------------------------------------------------
/tests/python/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | # this software and associated documentation files (the "Software"), to deal in
5 | # the Software without restriction, including without limitation the rights to
6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | # of the Software, and to permit persons to whom the Software is furnished to do
8 | # so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in all
11 | # copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 | #
21 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | # of the code.
24 |
--------------------------------------------------------------------------------
/tests/python/chwise_conv.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | # this software and associated documentation files (the "Software"), to deal in
5 | # the Software without restriction, including without limitation the rights to
6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | # of the Software, and to permit persons to whom the Software is furnished to do
8 | # so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in all
11 | # copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 | #
21 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | # of the code.
24 | import torch
25 | import unittest
26 |
27 | from MinkowskiEngine import SparseTensor, MinkowskiChannelwiseConvolution
28 | import MinkowskiEngine as ME
29 |
30 |
31 | from tests.common import data_loader
32 |
33 |
34 | def get_random_coords(dimension=2, tensor_stride=2):
35 | torch.manual_seed(0)
36 | # Create random coordinates with tensor stride == 2
37 | coords = torch.rand(10, dimension + 1)
38 | coords[:, :dimension] *= 5 # random coords
39 | coords[:, -1] *= 2 # random batch index
40 | coords = coords.floor().int()
41 | coords = ME.utils.sparse_quantize(coords)
42 | coords[:, :dimension] *= tensor_stride # make the tensor stride 2
43 | return coords, tensor_stride
44 |
45 |
46 | class TestConvolution(unittest.TestCase):
47 |
48 | def test(self):
49 | print(f"{self.__class__.__name__}: test")
50 | in_channels, D = 3, 2
51 | coords, feats, labels = data_loader(in_channels, batch_size=2)
52 |
53 | # Create random coordinates with tensor stride == 2
54 | out_coords, tensor_stride = get_random_coords()
55 |
56 | feats = feats.double()
57 | feats.requires_grad_()
58 | input = SparseTensor(feats, coords=coords)
59 |
60 | conv = MinkowskiChannelwiseConvolution(
61 | in_channels,
62 | kernel_size=3,
63 | stride=1,
64 | bias=False,
65 | dimension=D).double()
66 |
67 | print('Initial input: ', input)
68 | output = conv(input)
69 | print('Conv output: ', output)
70 |
71 | output.F.sum().backward()
72 | print(input.F.grad)
73 |
74 | def test_gpu(self):
75 | print(f"{self.__class__.__name__}: test_gpu")
76 | if not torch.cuda.is_available():
77 | return
78 |
79 | device = torch.device('cuda')
80 | in_channels, D = 3, 2
81 | coords, feats, labels = data_loader(in_channels, batch_size=2)
82 |
83 | # Create random coordinates with tensor stride == 2
84 | out_coords, tensor_stride = get_random_coords()
85 |
86 | feats = feats.double()
87 | feats.requires_grad_()
88 | input = SparseTensor(feats, coords=coords).to(device)
89 | conv = MinkowskiChannelwiseConvolution(
90 | in_channels,
91 | kernel_size=3,
92 | stride=1,
93 | bias=False,
94 | dimension=D).double().to(device)
95 |
96 | print('Initial input: ', input)
97 | output = conv(input)
98 | print('Conv output: ', output)
99 |
100 |
101 | if __name__ == '__main__':
102 | unittest.main()
103 |
--------------------------------------------------------------------------------
/tests/python/common.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | # this software and associated documentation files (the "Software"), to deal in
5 | # the Software without restriction, including without limitation the rights to
6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | # of the Software, and to permit persons to whom the Software is furnished to do
8 | # so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in all
11 | # copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 | #
21 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | # of the code.
24 | import os
25 | import numpy as np
26 |
27 | import torch
28 | import MinkowskiEngine as ME
29 |
30 | from urllib.request import urlretrieve
31 |
32 | if not os.path.isfile("1.ply"):
33 | urlretrieve("http://cvgl.stanford.edu/data2/minkowskiengine/1.ply", "1.ply")
34 |
35 |
36 | def load_file(file_name):
37 | try:
38 | import open3d as o3d
39 | except ImportError:
40 | raise ImportError("Please install open3d with `pip install open3d`.")
41 |
42 | pcd = o3d.io.read_point_cloud(file_name)
43 | coords = np.array(pcd.points)
44 | colors = np.array(pcd.colors)
45 | return coords, colors, pcd
46 |
47 |
48 | def get_coords(data):
49 | coords = []
50 | for i, row in enumerate(data):
51 | for j, col in enumerate(row):
52 | if col != " ":
53 | coords.append([i, j])
54 | return np.array(coords)
55 |
56 |
57 | def data_loader(
58 | nchannel=3,
59 | max_label=5,
60 | is_classification=True,
61 | seed=-1,
62 | batch_size=2,
63 | dtype=torch.float32,
64 | ):
65 | if seed >= 0:
66 | torch.manual_seed(seed)
67 |
68 | data = [" X ", " X X ", " XXXXX "]
69 |
70 | # Generate coordinates
71 | coords = [get_coords(data) for i in range(batch_size)]
72 | coords = ME.utils.batched_coordinates(coords)
73 |
74 | # features and labels
75 | N = len(coords)
76 | feats = torch.arange(N * nchannel).view(N, nchannel).to(dtype)
77 | label = (torch.rand(batch_size if is_classification else N) * max_label).long()
78 | return coords, feats, label
79 |
--------------------------------------------------------------------------------
/tests/python/conv_on_coords.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | # this software and associated documentation files (the "Software"), to deal in
5 | # the Software without restriction, including without limitation the rights to
6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | # of the Software, and to permit persons to whom the Software is furnished to do
8 | # so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in all
11 | # copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 | #
21 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | # of the code.
24 | import torch
25 | import unittest
26 |
27 | from MinkowskiEngine import SparseTensor, MinkowskiConvolution, \
28 | MinkowskiConvolutionTranspose
29 | import MinkowskiEngine as ME
30 |
31 |
32 | from tests.common import data_loader
33 |
34 |
35 | def get_random_coords(dimension=2, tensor_stride=2):
36 | torch.manual_seed(0)
37 | # Create random coordinates with tensor stride == 2
38 | coords = torch.rand(10, dimension + 1)
39 | coords[:, :dimension] *= 5 # random coords
40 | coords[:, -1] *= 2 # random batch index
41 | coords = coords.floor().int()
42 | coords = ME.utils.sparse_quantize(coords)
43 | coords[:, :dimension] *= tensor_stride # make the tensor stride 2
44 | return coords, tensor_stride
45 |
46 |
47 | class TestConvolution(unittest.TestCase):
48 |
49 | def test(self):
50 | print(f"{self.__class__.__name__}: test")
51 | in_channels, out_channels, D = 2, 3, 2
52 | coords, feats, labels = data_loader(in_channels, batch_size=2)
53 |
54 | # Create random coordinates with tensor stride == 2
55 | out_coords, tensor_stride = get_random_coords()
56 |
57 | feats = feats.double()
58 | feats.requires_grad_()
59 | input = SparseTensor(feats, coords=coords)
60 | cm = input.coords_man
61 | print(cm._get_coords_key(1))
62 |
63 | conv = MinkowskiConvolution(
64 | in_channels,
65 | out_channels,
66 | kernel_size=3,
67 | stride=1,
68 | bias=False,
69 | dimension=D).double()
70 |
71 | print('Initial input: ', input)
72 | print('Specified output coords: ', out_coords)
73 | output = conv(input, out_coords)
74 |
75 | # To specify the tensor stride
76 | out_coords_key = cm.create_coords_key(out_coords, tensor_stride=2)
77 | output = conv(input, out_coords_key)
78 | print('Conv output: ', output)
79 |
80 | output.F.sum().backward()
81 | print(input.F.grad)
82 |
83 | def test_tr(self):
84 | print(f"{self.__class__.__name__}: test_tr")
85 | in_channels, out_channels, D = 2, 3, 2
86 | coords, feats, labels = data_loader(in_channels, batch_size=2)
87 | # tensor stride must be at least 2 for convolution transpose with stride 2
88 | coords[:, :2] *= 2
89 | out_coords = torch.rand(10, 3)
90 | out_coords[:, :2] *= 10 # random coords
91 | out_coords[:, 2] *= 2 # random batch index
92 | out_coords = out_coords.floor().int()
93 |
94 | feats = feats.double()
95 | feats.requires_grad_()
96 |
97 | input = SparseTensor(feats, coords=coords, tensor_stride=2)
98 | cm = input.coords_man
99 | print(cm._get_coords_key(2))
100 |
101 | conv_tr = MinkowskiConvolutionTranspose(
102 | in_channels,
103 | out_channels,
104 | kernel_size=3,
105 | stride=2,
106 | bias=False,
107 | dimension=D).double()
108 | print('Initial input: ', input)
109 | print('Specified output coords: ', out_coords)
110 | output = conv_tr(input, out_coords)
111 | print('Conv output: ', output)
112 |
113 | output.F.sum().backward()
114 | print(input.F.grad)
115 |
116 |
117 | if __name__ == '__main__':
118 | unittest.main()
119 |
--------------------------------------------------------------------------------
/tests/python/direct_pool.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2021 NVIDIA CORPORATION.
2 | # Copyright (c) 2018-2020 Chris Choy (chrischoy@ai.stanford.edu).
3 | #
4 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
5 | # this software and associated documentation files (the "Software"), to deal in
6 | # the Software without restriction, including without limitation the rights to
7 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8 | # of the Software, and to permit persons to whom the Software is furnished to do
9 | # so, subject to the following conditions:
10 | #
11 | # The above copyright notice and this permission notice shall be included in all
12 | # copies or substantial portions of the Software.
13 | #
14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | # SOFTWARE.
21 | #
22 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
23 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
24 | # of the code.
25 | import torch
26 | import unittest
27 |
28 | from MinkowskiEngine import MinkowskiDirectMaxPoolingFunction
29 |
30 | from utils.gradcheck import gradcheck
31 |
32 |
33 | class TestCase(unittest.TestCase):
34 | def test(self):
35 | if not torch.cuda.is_available():
36 | return
37 | pool = MinkowskiDirectMaxPoolingFunction()
38 | in_map = torch.randint(0, 5, (10,)).int()
39 | out_map = torch.randint(0, 3, (10,)).int()
40 | in_feat = torch.rand(5, 16).double()
41 | in_feat.requires_grad_()
42 | out_nrows = 3
43 | out_feat = pool.apply(in_map, out_map, in_feat, out_nrows)
44 | print(out_feat)
45 | out_feat.sum().backward()
46 |
47 | self.assertTrue(
48 | gradcheck(
49 | pool,
50 | (in_map, out_map, in_feat, out_nrows),
51 | )
52 | )
53 |
54 | if not torch.cuda.is_available():
55 | return
56 |
57 | in_map = in_map.cuda()
58 | out_map = out_map.cuda()
59 | in_feat = in_feat.cuda()
60 |
61 | out_feat = pool.apply(in_map, out_map, in_feat, out_nrows)
62 | print(out_feat)
63 |
64 | self.assertTrue(
65 | gradcheck(
66 | pool,
67 | (in_map, out_map, in_feat, out_nrows),
68 | )
69 | )
70 |
71 | def test_long(self):
72 | if not torch.cuda.is_available():
73 | return
74 | pool = MinkowskiDirectMaxPoolingFunction()
75 | in_map = torch.randint(0, 5, (10,))
76 | out_map = torch.randint(0, 3, (10,))
77 | in_feat = torch.rand(5, 16).double()
78 | in_feat.requires_grad_()
79 | out_nrows = 3
80 | out_feat = pool.apply(in_map, out_map, in_feat, out_nrows)
81 | print(out_feat)
82 | out_feat.sum().backward()
83 |
84 | self.assertTrue(
85 | gradcheck(
86 | pool,
87 | (in_map, out_map, in_feat, out_nrows),
88 | )
89 | )
90 |
91 | if not torch.cuda.is_available():
92 | return
93 |
94 | in_map = in_map.cuda()
95 | out_map = out_map.cuda()
96 | in_feat = in_feat.cuda()
97 |
98 | out_feat = pool.apply(in_map, out_map, in_feat, out_nrows)
99 | print(out_feat)
100 |
101 | self.assertTrue(
102 | gradcheck(
103 | pool,
104 | (in_map, out_map, in_feat, out_nrows),
105 | )
106 | )
107 |
--------------------------------------------------------------------------------
/tests/python/global.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | # this software and associated documentation files (the "Software"), to deal in
5 | # the Software without restriction, including without limitation the rights to
6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | # of the Software, and to permit persons to whom the Software is furnished to do
8 | # so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in all
11 | # copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 | #
21 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | # of the code.
24 | import os
25 | import argparse
26 | import numpy as np
27 | from urllib.request import urlretrieve
28 | try:
29 | import open3d as o3d
30 | except ImportError:
31 | raise ImportError('Please install open3d with `pip install open3d`.')
32 |
33 | import torch
34 | import MinkowskiEngine as ME
35 | from examples.common import Timer
36 |
37 | # Check if the weights and file exist and download
38 | if not os.path.isfile('1.ply'):
39 | print('Downloading a room ply file...')
40 | urlretrieve("http://cvgl.stanford.edu/data2/minkowskiengine/1.ply", '1.ply')
41 |
42 | parser = argparse.ArgumentParser()
43 | parser.add_argument('--file_name', type=str, default='1.ply')
44 | parser.add_argument('--voxel_size', type=float, default=0.02)
45 | parser.add_argument('--batch_size', type=int, default=2)
46 | parser.add_argument('--max_kernel_size', type=int, default=7)
47 |
48 |
49 | def load_file(file_name, voxel_size):
50 | pcd = o3d.io.read_point_cloud(file_name)
51 | coords = np.array(pcd.points)
52 | feats = np.array(pcd.colors)
53 |
54 | quantized_coords = np.floor(coords / voxel_size)
55 | unique_coords, unique_feats = ME.utils.sparse_quantize(quantized_coords, feats)
56 | return unique_coords, unique_feats, pcd
57 |
58 |
59 | def generate_input_sparse_tensor(file_name, voxel_size=0.05, batch_size=1):
60 | # Create a batch, this process is done in a data loader during training in parallel.
61 | batch = [
62 | load_file(file_name, voxel_size),
63 | ] * batch_size
64 | coordinates_, featrues_, pcds = list(zip(*batch))
65 | coordinates, features = ME.utils.sparse_collate(coordinates_, featrues_)
66 |
67 | # Normalize features and create a sparse tensor
68 | return features, coordinates
69 |
70 |
71 | if __name__ == '__main__':
72 | config = parser.parse_args()
73 | device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
74 |
75 | # Define a model and load the weights
76 | feats = [3, 8, 16, 32, 64, 128]
77 | features, coordinates = generate_input_sparse_tensor(
78 | config.file_name,
79 | voxel_size=config.voxel_size,
80 | batch_size=config.batch_size)
81 | pool = ME.MinkowskiGlobalAvgPooling()
82 |
83 | # Measure time
84 | print('Forward')
85 | for feat in feats:
86 | timer = Timer()
87 | features = torch.rand(len(coordinates), feat).to(device)
88 |
89 | # Feed-forward pass and get the prediction
90 | for i in range(20):
91 | sinput = ME.SparseTensor(features, coordinates=coordinates, device=device)
92 |
93 | timer.tic()
94 | soutput = pool(sinput)
95 | timer.toc()
96 | print(
97 | f'{timer.min_time:.12f} for feature size: {feat} with {len(sinput)} voxel'
98 | )
99 |
100 | print('Backward')
101 | for feat in feats:
102 | timer = Timer()
103 | sinput._F = torch.rand(len(sinput), feat).to(device).requires_grad_()
104 | soutput = pool(sinput)
105 | loss = soutput.F.sum()
106 | # Feed-forward pass and get the prediction
107 | for i in range(20):
108 | timer.tic()
109 | loss.backward()
110 | timer.toc()
111 | print(
112 | f'{timer.min_time:.12f} for feature size {feat} with {len(sinput)} voxel'
113 | )
114 |
--------------------------------------------------------------------------------
/tests/python/kernel_map.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
2 | #
3 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | # this software and associated documentation files (the "Software"), to deal in
5 | # the Software without restriction, including without limitation the rights to
6 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | # of the Software, and to permit persons to whom the Software is furnished to do
8 | # so, subject to the following conditions:
9 | #
10 | # The above copyright notice and this permission notice shall be included in all
11 | # copies or substantial portions of the Software.
12 | #
13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | # SOFTWARE.
20 | #
21 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
22 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
23 | # of the code.
24 | import unittest
25 |
26 | import torch
27 |
28 | from MinkowskiEngine import SparseTensor, MinkowskiConvolution, MinkowskiAlgorithm
29 |
30 | from tests.python.common import data_loader
31 |
32 |
33 | class TestKernelMap(unittest.TestCase):
34 | def test_kernelmap_gpu(self):
35 | print(f"{self.__class__.__name__}: test_kernelmap_gpu")
36 | if not torch.cuda.is_available():
37 | return
38 |
39 | in_channels, out_channels, D = 2, 3, 2
40 | coords, feats, labels = data_loader(in_channels)
41 | feats = feats.double()
42 | feats.requires_grad_()
43 | input = SparseTensor(
44 | feats,
45 | coordinates=coords,
46 | minkowski_algorithm=MinkowskiAlgorithm.SPEED_OPTIMIZED,
47 | device="cuda",
48 | )
49 |
50 | # Initialize context
51 | conv = (
52 | MinkowskiConvolution(
53 | in_channels,
54 | out_channels,
55 | kernel_size=3,
56 | stride=2,
57 | bias=True,
58 | dimension=D,
59 | )
60 | .double()
61 | .cuda()
62 | )
63 | output = conv(input)
64 |
65 | iC = input.C.cpu().numpy()
66 | oC = output.C.cpu().numpy()
67 | print(iC)
68 | print(oC)
69 | kernel_maps = output.coordinate_manager.kernel_map(
70 | 1,
71 | 2,
72 | stride=2,
73 | kernel_size=3,
74 | )
75 | for kernel_index, in_out_map in kernel_maps.items():
76 | for i, o in zip(in_out_map[0], in_out_map[1]):
77 | print(kernel_index, iC[i], "->", oC[o])
78 | self.assertTrue(sum(len(in_map[0]) for k, in_map in kernel_maps.items()) == 16)
79 |
80 | def test_kernelmap(self):
81 | print(f"{self.__class__.__name__}: test_kernelmap")
82 | in_channels, out_channels, D = 2, 3, 2
83 | coords, feats, labels = data_loader(in_channels)
84 | feats = feats.double()
85 | feats.requires_grad_()
86 | input = SparseTensor(feats, coordinates=coords)
87 |
88 | # Initialize context
89 | conv = MinkowskiConvolution(
90 | in_channels,
91 | out_channels,
92 | kernel_size=3,
93 | stride=2,
94 | bias=True,
95 | dimension=D,
96 | ).double()
97 | output = conv(input)
98 |
99 | iC = input.C.numpy()
100 | oC = output.C.numpy()
101 | print(iC)
102 | print(oC)
103 | kernel_maps = output.coordinate_manager.kernel_map(
104 | 1, 2, stride=2, kernel_size=3
105 | )
106 | for kernel_index, in_out_map in kernel_maps.items():
107 | for i, o in zip(in_out_map[0], in_out_map[1]):
108 | print(kernel_index, iC[i], "->", oC[o])
109 | self.assertTrue(sum(len(in_map[0]) for k, in_map in kernel_maps.items()) == 16)
110 |
--------------------------------------------------------------------------------
/tests/python/norm.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2020 NVIDIA CORPORATION.
2 | # Copyright (c) 2018-2020 Chris Choy (chrischoy@ai.stanford.edu).
3 | #
4 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
5 | # this software and associated documentation files (the "Software"), to deal in
6 | # the Software without restriction, including without limitation the rights to
7 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8 | # of the Software, and to permit persons to whom the Software is furnished to do
9 | # so, subject to the following conditions:
10 | #
11 | # The above copyright notice and this permission notice shall be included in all
12 | # copies or substantial portions of the Software.
13 | #
14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | # SOFTWARE.
21 | #
22 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
23 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
24 | # of the code.
25 | import torch
26 | import unittest
27 |
28 | from MinkowskiEngine import (
29 | SparseTensor,
30 | MinkowskiInstanceNorm,
31 | MinkowskiInstanceNormFunction,
32 | )
33 | from utils.gradcheck import gradcheck
34 |
35 | from tests.python.common import data_loader
36 |
37 |
38 | class TestNormalization(unittest.TestCase):
39 | def test_inst_norm(self):
40 | in_channels = 2
41 | coords, feats, labels = data_loader(in_channels)
42 | feats = feats.double()
43 | input = SparseTensor(feats, coords)
44 | input.F.requires_grad_()
45 | norm = MinkowskiInstanceNorm(num_features=in_channels).double()
46 |
47 | out = norm(input)
48 | print(out)
49 |
50 | fn = MinkowskiInstanceNormFunction()
51 | self.assertTrue(
52 | gradcheck(
53 | fn, (input.F, input.coordinate_map_key, None, input.coordinate_manager)
54 | )
55 | )
56 |
57 | def test_inst_norm_gpu(self):
58 | in_channels = 2
59 | coords, feats, labels = data_loader(in_channels)
60 | feats = feats.double()
61 |
62 | device = torch.device("cuda")
63 | input = SparseTensor(feats, coords, device=device)
64 | input.F.requires_grad_()
65 | norm = MinkowskiInstanceNorm(num_features=in_channels).to(device).double()
66 |
67 | out = norm(input)
68 | print(out)
69 |
70 | fn = MinkowskiInstanceNormFunction()
71 | self.assertTrue(
72 | gradcheck(
73 | fn, (input.F, input.coordinate_map_key, None, input.coordinate_manager)
74 | )
75 | )
76 |
77 |
78 | if __name__ == "__main__":
79 | unittest.main()
80 |
--------------------------------------------------------------------------------
/tests/python/union.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2020 NVIDIA CORPORATION.
2 | # Copyright (c) Chris Choy (chrischoy@ai.stanford.edu).
3 | #
4 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
5 | # this software and associated documentation files (the "Software"), to deal in
6 | # the Software without restriction, including without limitation the rights to
7 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8 | # of the Software, and to permit persons to whom the Software is furnished to do
9 | # so, subject to the following conditions:
10 | #
11 | # The above copyright notice and this permission notice shall be included in all
12 | # copies or substantial portions of the Software.
13 | #
14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | # SOFTWARE.
21 | #
22 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
23 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
24 | # of the code.
25 | import torch
26 | import unittest
27 |
28 | import MinkowskiEngine as ME
29 | from MinkowskiEngine import SparseTensor, MinkowskiUnion
30 |
31 |
32 | class TestUnion(unittest.TestCase):
33 | def test_union(self):
34 | coords1 = torch.IntTensor([[0, 0], [0, 1]])
35 | coords2 = torch.IntTensor([[0, 1], [1, 1]])
36 | feats1 = torch.DoubleTensor([[1], [2]])
37 | feats2 = torch.DoubleTensor([[3], [4]])
38 | union = MinkowskiUnion()
39 |
40 | input1 = SparseTensor(
41 | coordinates=ME.utils.batched_coordinates([coords1]), features=feats1
42 | )
43 |
44 | input2 = SparseTensor(
45 | coordinates=ME.utils.batched_coordinates([coords2]),
46 | features=feats2,
47 | coordinate_manager=input1.coordinate_manager, # Must use same coords manager
48 | )
49 |
50 | input1.requires_grad_()
51 | input2.requires_grad_()
52 | output = union(input1, input2)
53 | print(output)
54 |
55 | self.assertTrue(len(output) == 3)
56 | self.assertTrue(5 in output.F)
57 | output.F.sum().backward()
58 |
59 | # Grad of sum feature is 1.
60 | self.assertTrue(torch.prod(input1.F.grad) == 1)
61 | self.assertTrue(torch.prod(input2.F.grad) == 1)
62 |
63 | def test_union_gpu(self):
64 | device = torch.device("cuda")
65 |
66 | coords1 = torch.IntTensor([[0, 0], [0, 1]])
67 | coords2 = torch.IntTensor([[0, 1], [1, 1]])
68 | feats1 = torch.DoubleTensor([[1], [2]])
69 | feats2 = torch.DoubleTensor([[3], [4]])
70 | union = MinkowskiUnion()
71 |
72 | input1 = SparseTensor(feats1, coords1, device=device, requires_grad=True)
73 | input2 = SparseTensor(
74 | feats2,
75 | coords2,
76 | device=device,
77 | coordinate_manager=input1.coordinate_manager,
78 | requires_grad=True,
79 | )
80 | output_gpu = union(input1, input2)
81 | output_gpu.F.sum().backward()
82 | print(output_gpu)
83 | self.assertTrue(len(output_gpu) == 3)
84 | self.assertTrue(1 in output_gpu.F)
85 | self.assertTrue(5 in output_gpu.F)
86 | self.assertTrue(4 in output_gpu.F)
87 |
88 |
89 | if __name__ == "__main__":
90 | unittest.main()
91 |
--------------------------------------------------------------------------------
/tests/python/utility_functions.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2020 NVIDIA CORPORATION.
2 | # Copyright (c) 2018-2020 Chris Choy (chrischoy@ai.stanford.edu).
3 | #
4 | # Permission is hereby granted, free of charge, to any person obtaining a copy of
5 | # this software and associated documentation files (the "Software"), to deal in
6 | # the Software without restriction, including without limitation the rights to
7 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8 | # of the Software, and to permit persons to whom the Software is furnished to do
9 | # so, subject to the following conditions:
10 | #
11 | # The above copyright notice and this permission notice shall be included in all
12 | # copies or substantial portions of the Software.
13 | #
14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | # SOFTWARE.
21 | #
22 | # Please cite "4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural
23 | # Networks", CVPR'19 (https://arxiv.org/abs/1904.08755) if you use any part
24 | # of the code.
25 | import torch
26 | import unittest
27 |
28 | import MinkowskiEngine as ME
29 |
30 |
31 | class TestUtility(unittest.TestCase):
32 | def test(self):
33 | self.assertTrue(ME.is_cuda_available() == torch.cuda.is_available())
34 | if ME.is_cuda_available():
35 | print(ME.cuda_version())
36 | print(ME.get_gpu_memory_info())
37 |
--------------------------------------------------------------------------------
/tests/run_test.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 |
4 | if __name__ == '__main__':
5 | unittest.main()
6 |
--------------------------------------------------------------------------------