Open3D (C++ API)  0.20.0
Loading...
Searching...
No Matches
TorchOpen3DBridge.h
Go to the documentation of this file.
1// ----------------------------------------------------------------------------
2// - Open3D: www.open3d.org -
3// ----------------------------------------------------------------------------
4// Copyright (c) 2018-2026 www.open3d.org
5// SPDX-License-Identifier: MIT
6// ----------------------------------------------------------------------------
7
8// Zero-copy bridging helpers between torch::Tensor (CUDA/XPU) and
9// open3d::core::Tensor, implemented on top of the DLPack protocol that both
10// libraries already support (Open3D: core::Tensor::ToDLPack/FromDLPack;
11// PyTorch: at::toDLPack/at::fromDLPack). This avoids re-implementing the
12// device/dtype/shape marshalling that DLPack already provides. Open3D's
13// core/DLPack.h and PyTorch's vendored ATen/dlpack.h are the same DLPack
14// v1.3 header (byte-identical apart from clang-format whitespace), so
15// exchanging `DLManagedTensor*` between the two is ABI-safe.
16
17#pragma once
18
19#include <ATen/DLConvertor.h>
20
21#include "open3d/core/Tensor.h"
22#include "torch/script.h"
23
24namespace open3d {
25namespace ml {
26namespace torch_bridge {
27// Anonymous namespace: each including .cpp file (KnnSearchOps.cpp,
28// KnnSearchOpKernelSYCL.cpp) gets its own internal-linkage copy of these
29// helpers, keeping them out of open3d_torch_ops.so's exported symbol table
30// since they are implementation details, not part of any public API.
31namespace {
32
36inline core::Tensor TorchToOpen3DTensor(const torch::Tensor& t) {
37 // PyTorch's DLPack export of a 0-element tensor uses a null data
38 // pointer, which core::Tensor::FromDLPack can wrap directly (unlike
39 // libtorch's own DLPack *import*, which cannot resolve an XPU device
40 // from a null pointer -- see Open3DToTorchTensor below), so no special
41 // case is needed in this direction.
42 DLManagedTensor* dlmt = at::toDLPack(t);
43 return core::Tensor::FromDLPack(dlmt);
44}
45
50inline torch::Tensor Open3DToTorchTensor(const core::Tensor& t) {
51 // libtorch's DLPack *import* (at::dlDeviceToTorchDevice) resolves the
52 // XPU device by calling getDeviceFromPtr() on the DLTensor's data
53 // pointer, which TORCH_CHECK-fails for a null pointer ("Can't get ATen
54 // device for XPU without XPU data."). Open3D's SYCL/CUDA allocators
55 // return a null pointer for a 0-byte allocation (e.g. 0 query points ->
56 // 0 neighbors), so a 0-element tensor must be special-cased: allocate a
57 // fresh, empty torch::Tensor directly instead of importing via DLPack.
58 // Confirmed this is a libtorch-side limitation, not specific to Open3D:
59 // torch.empty(0, device='xpu') fails the same DLPack roundtrip through
60 // torch's own to_dlpack()/from_dlpack().
61 if (t.NumElements() == 0) {
62 const core::Device& device = t.GetDevice();
63 c10::Device torch_device(c10::kCPU);
64 if (device.IsCUDA()) {
65 torch_device = c10::Device(c10::kCUDA, device.GetID());
66 } else if (device.IsSYCL()) {
67 torch_device = c10::Device(c10::kXPU, device.GetID());
68 } else if (device.IsCPU()) {
69 torch_device = c10::Device(c10::kCPU);
70 } else {
71 TORCH_CHECK(false,
72 "Open3DToTorchTensor: unsupported Open3D device ",
73 device.ToString());
74 }
75
76 const core::Dtype& dtype = t.GetDtype();
77 torch::ScalarType scalar_type;
78 if (dtype == core::Float32) {
79 scalar_type = torch::kFloat32;
80 } else if (dtype == core::Float64) {
81 scalar_type = torch::kFloat64;
82 } else if (dtype == core::Int32) {
83 scalar_type = torch::kInt32;
84 } else if (dtype == core::Int64) {
85 scalar_type = torch::kInt64;
86 } else {
87 TORCH_CHECK(false, "Open3DToTorchTensor: unsupported Open3D dtype ",
88 dtype.ToString());
89 }
90
91 const core::SizeVector& shape = t.GetShapeRef();
92 std::vector<int64_t> sizes(shape.begin(), shape.end());
93 return torch::empty(sizes,
94 torch::dtype(scalar_type).device(torch_device));
95 }
96
97 DLManagedTensor* dlmt = t.ToDLPack();
98 return at::fromDLPack(dlmt);
99}
100
101} // namespace
102} // namespace torch_bridge
103} // namespace ml
104} // namespace open3d
double t
Definition SurfaceReconstructionPoisson.cpp:175
Definition Device.h:18
bool IsSYCL() const
Returns true iff device type is SYCL GPU.
Definition Device.h:54
int GetID() const
Returns the device index (within the same device type).
Definition Device.h:63
bool IsCPU() const
Returns true iff device type is CPU.
Definition Device.h:48
bool IsCUDA() const
Returns true iff device type is CUDA.
Definition Device.h:51
std::string ToString() const
Returns string representation of device, e.g. "CPU:0", "CUDA:0".
Definition Device.cpp:94
Definition Dtype.h:20
std::string ToString() const
Definition Dtype.h:64
Definition SizeVector.h:69
iterator begin()
Definition SmallVector.h:302
iterator end()
Definition SmallVector.h:304
Definition Tensor.h:32
static Tensor FromDLPack(const DLManagedTensor *dlmt, std::function< void(void *)> deleter=nullptr)
Convert DLManagedTensor to Tensor (DLPack v0.x).
Definition Tensor.cpp:1987
const Dtype Int64
Definition Dtype.cpp:47
const Dtype Int32
Definition Dtype.cpp:46
const Dtype Float64
Definition Dtype.cpp:43
const Dtype Float32
Definition Dtype.cpp:42
Definition PinholeCameraIntrinsic.cpp:16
C Tensor object, manage memory of DLTensor. This data structure is intended to facilitate the borrowi...
Definition DLPack.h:319