ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
Solve.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
10 #ifdef BUILD_CUDA_MODULE
11 #include <cuda_runtime_api.h>
12 #endif
13 
14 #include <unordered_map>
15 
18 
19 namespace cloudViewer {
20 namespace core {
21 
22 void Solve(const Tensor &A, const Tensor &B, Tensor &X) {
24  const Device device = A.GetDevice();
25  const Dtype dtype = A.GetDtype();
26 
27  AssertTensorDtype(B, dtype);
28  AssertTensorDevice(B, device);
29 
30  // Check dimensions
31  SizeVector A_shape = A.GetShape();
32  SizeVector B_shape = B.GetShape();
33  if (A_shape.size() != 2) {
34  utility::LogError("Tensor A must be 2D, but got {}D", A_shape.size());
35  }
36  if (A_shape[0] != A_shape[1]) {
37  utility::LogError("Tensor A must be square, but got {} x {}.",
38  A_shape[0], A_shape[1]);
39  }
40  if (B_shape.size() != 1 && B_shape.size() != 2) {
42  "Tensor B must be 1D (vector) or 2D (matrix), but got {}D",
43  B_shape.size());
44  }
45  if (B_shape[0] != A_shape[0]) {
46  utility::LogError("Tensor A and B's first dimension mismatch.");
47  }
48 
49  int64_t n = A_shape[0];
50  int64_t k = B_shape.size() == 2 ? B_shape[1] : 1;
51  if (n == 0 || k == 0) {
53  "Tensor shapes should not contain dimensions with zero.");
54  }
55 
56  // A and B are modified in-place
57  Tensor A_copy = A.T().Clone();
58  void *A_data = A_copy.GetDataPtr();
59 
60  X = B.T().Clone();
61  void *B_data = X.GetDataPtr();
62 
63  if (device.IsSYCL()) {
64 #ifdef BUILD_SYCL_MODULE
65  Tensor ipiv = Tensor::Empty({n}, core::Int64, device);
66  void *ipiv_data = ipiv.GetDataPtr();
67 
68  SolveSYCL(A_data, B_data, ipiv_data, n, k, dtype, device);
69 #else
70  utility::LogError("Unimplemented device.");
71 #endif
72  } else if (device.IsCUDA()) {
73 #ifdef BUILD_CUDA_MODULE
74  CUDAScopedDevice scoped_device(device);
75  Tensor ipiv = Tensor::Empty({n}, core::Int32, device);
76  void *ipiv_data = ipiv.GetDataPtr();
77 
78  SolveCUDA(A_data, B_data, ipiv_data, n, k, dtype, device);
79 #else
80  utility::LogError("Unimplemented device.");
81 #endif
82  } else {
83  Dtype ipiv_dtype;
84  if (sizeof(CLOUDVIEWER_CPU_LINALG_INT) == 4) {
85  ipiv_dtype = core::Int32;
86  } else if (sizeof(CLOUDVIEWER_CPU_LINALG_INT) == 8) {
87  ipiv_dtype = core::Int64;
88  } else {
89  utility::LogError("Unsupported CLOUDVIEWER_CPU_LINALG_INT type.");
90  }
91  Tensor ipiv = Tensor::Empty({n}, ipiv_dtype, device);
92  void *ipiv_data = ipiv.GetDataPtr();
93 
94  SolveCPU(A_data, B_data, ipiv_data, n, k, dtype, device);
95  }
96  X = X.T();
97 }
98 } // namespace core
99 } // namespace cloudViewer
Common CUDA utilities.
#define CLOUDVIEWER_CPU_LINALG_INT
void * X
Definition: SmallVector.cpp:45
#define AssertTensorDevice(tensor,...)
Definition: TensorCheck.h:45
#define AssertTensorDtype(tensor,...)
Definition: TensorCheck.h:21
#define AssertTensorDtypes(tensor,...)
Definition: TensorCheck.h:33
When CUDA is not enabled, this is a dummy class.
Definition: CUDAUtils.h:214
Dtype GetDtype() const
Definition: Tensor.h:1164
Device GetDevice() const override
Definition: Tensor.cpp:1435
Tensor Clone() const
Copy Tensor to the same device.
Definition: Tensor.h:502
static Tensor Empty(const SizeVector &shape, Dtype dtype, const Device &device=Device("CPU:0"))
Create a tensor with uninitialized values.
Definition: Tensor.cpp:400
SizeVector GetShape() const
Definition: Tensor.h:1127
Tensor T() const
Expects input to be <= 2-D Tensor by swapping dimension 0 and 1.
Definition: Tensor.cpp:1079
#define LogError(...)
Definition: Logging.h:60
void SolveSYCL(void *A_data, void *B_data, void *ipiv_data, int64_t n, int64_t k, Dtype dtype, const Device &device)
Definition: SolveSYCL.cpp:19
void SolveCUDA(void *A_data, void *B_data, void *ipiv_data, int64_t n, int64_t k, Dtype dtype, const Device &device)
Definition: SolveCUDA.cpp:20
void Solve(const Tensor &A, const Tensor &B, Tensor &X)
Solve AX = B with LU decomposition. A is a square matrix.
Definition: Solve.cpp:22
const Dtype Int64
Definition: Dtype.cpp:47
void SolveCPU(void *A_data, void *B_data, void *ipiv_data, int64_t n, int64_t k, Dtype dtype, const Device &device)
Definition: SolveCPU.cpp:15
const Dtype Float64
Definition: Dtype.cpp:43
const Dtype Int32
Definition: Dtype.cpp:46
const Dtype Float32
Definition: Dtype.cpp:42
Generic file read and write utility for python interface.