mirror of
https://github.com/ceres-solver/ceres-solver.git
synced 2026-08-29 16:40:38 +08:00
cb6ad463d0
On problem-744-543562-pre.txt The time spent in linear solver on my M1 Pro is eigen 81.550970 eigen+mixed 54.107383 LAPACK 47.078127 LAPACK+mixed 28.639868 Solution quality is unaffected. The implementation of RefinedDenseCholesky and DenseIterativeRefiner are straightforward ports of RefinedSparseCholesky and SparseIterativeRefiner (formerly IterativeRefiner). It maybe possible to refactor the SparseCholesky and DenseCholesky interfaces so that this code duplication can be removed in the future. Change-Id: I921334224cb97629a60390f2add822de207f7923
117 lines
4.3 KiB
C++
117 lines
4.3 KiB
C++
// Ceres Solver - A fast non-linear least squares minimizer
|
|
// Copyright 2022 Google Inc. All rights reserved.
|
|
// http://ceres-solver.org/
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are met:
|
|
//
|
|
// * Redistributions of source code must retain the above copyright notice,
|
|
// this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
// this list of conditions and the following disclaimer in the documentation
|
|
// and/or other materials provided with the distribution.
|
|
// * Neither the name of Google Inc. nor the names of its contributors may be
|
|
// used to endorse or promote products derived from this software without
|
|
// specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
// POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
// Author: joydeepb@cs.utexas.edu (Joydeep Biswas)
|
|
|
|
#ifndef CERES_INTERNAL_CUDA_BUFFER_H_
|
|
#define CERES_INTERNAL_CUDA_BUFFER_H_
|
|
|
|
#include "ceres/internal/config.h"
|
|
|
|
#ifndef CERES_NO_CUDA
|
|
|
|
#include <vector>
|
|
|
|
#include "cuda_runtime.h"
|
|
#include "glog/logging.h"
|
|
|
|
// An encapsulated buffer to maintain GPU memory, and handle transfers between
|
|
// GPU and system memory. It is the responsibility of the user to ensure that
|
|
// the appropriate GPU device is selected before each subroutine is called. This
|
|
// is particularly important when using multiple GPU devices on different CPU
|
|
// threads, since active Cuda devices are determined by the cuda runtime on a
|
|
// per-thread basis. Note that unless otherwise specified, all methods use the
|
|
// default stream, and are synchronous.
|
|
template <typename T>
|
|
class CudaBuffer {
|
|
public:
|
|
CudaBuffer() = default;
|
|
CudaBuffer(const CudaBuffer&) = delete;
|
|
CudaBuffer& operator=(const CudaBuffer&) = delete;
|
|
|
|
~CudaBuffer() {
|
|
if (data_ != nullptr) {
|
|
CHECK_EQ(cudaFree(data_), cudaSuccess);
|
|
}
|
|
}
|
|
|
|
// Grow the GPU memory buffer if needed to accommodate data of the specified
|
|
// size
|
|
void Reserve(const size_t size) {
|
|
if (size > size_) {
|
|
if (data_ != nullptr) {
|
|
CHECK_EQ(cudaFree(data_), cudaSuccess);
|
|
}
|
|
CHECK_EQ(cudaMalloc(&data_, size * sizeof(T)), cudaSuccess);
|
|
size_ = size;
|
|
}
|
|
}
|
|
|
|
// Perform an asynchronous copy from CPU memory to GPU memory using the stream
|
|
// provided.
|
|
void CopyToGpuAsync(const T* data, const size_t size, cudaStream_t stream) {
|
|
Reserve(size);
|
|
CHECK_EQ(cudaMemcpyAsync(
|
|
data_, data, size * sizeof(T), cudaMemcpyHostToDevice, stream),
|
|
cudaSuccess);
|
|
}
|
|
|
|
// Perform an asynchronous copy from GPU memory using the stream provided.
|
|
void CopyFromGpuAsync(const T* data, const size_t size, cudaStream_t stream) {
|
|
Reserve(size);
|
|
CHECK_EQ(
|
|
cudaMemcpyAsync(
|
|
data_, data, size * sizeof(T), cudaMemcpyDeviceToDevice, stream),
|
|
cudaSuccess);
|
|
}
|
|
|
|
// Copy data from the GPU to CPU memory. This is necessarily synchronous since
|
|
// any potential GPU kernels that may be writing to the buffer must finish
|
|
// before the transfer happens.
|
|
void CopyToHost(T* data, const size_t size) {
|
|
CHECK(data_ != nullptr);
|
|
CHECK_EQ(cudaMemcpy(data, data_, size * sizeof(T), cudaMemcpyDeviceToHost),
|
|
cudaSuccess);
|
|
}
|
|
|
|
void CopyToGpu(const std::vector<T>& data) {
|
|
CopyToGpu(data.data(), data.size());
|
|
}
|
|
|
|
T* data() { return data_; }
|
|
const T* data() const { return data_; }
|
|
size_t size() const { return size_; }
|
|
|
|
private:
|
|
T* data_ = nullptr;
|
|
size_t size_ = 0;
|
|
};
|
|
|
|
#endif // CERES_NO_CUDA
|
|
|
|
#endif // CERES_INTERNAL_CUDA_BUFFER_H_
|