如何使用 Cuda 将动态特征向量传递给 GPU?
How to pass dynamic Eigen vector to GPU using Cuda?
我将学习如何将动态特征向量传输到 GPU 并将其取回。为此,我写了一段测试代码:
using Vector = Eigen::Matrix<float, Eigen::Dynamic, 1, Eigen::ColMajor>;
Vector vector;
uint64_t size = 6;
vector.resize(size);
for (uint64_t i = 0; i < size; ++i)
vector[i] = i;
uint64_t sizeInBytes = size * sizeof (float) + sizeof (vector);
Vector *vectorCuda;
cudaMalloc((void**)&vectorCuda, sizeInBytes);
cudaMemcpy(vectorCuda, &vector, sizeInBytes, cudaMemcpyKind::cudaMemcpyHostToDevice);
Vector result;
result.resize(size);
cudaMemcpy(&result, vectorCuda, sizeInBytes, cudaMemcpyKind::cudaMemcpyDeviceToHost);
cudaFree(vectorCuda);
std::cout << "result: " << std::endl << result << std::endl;
输出为:
result:
0
1
2
3
4
5
double free or corruption (fasttop)
所以我将数据传递给 GPU 并将其取回,但我收到了 SIGABRT 错误。错误发生在std::free(ptr):
1 __GI_raise raise.c 50 0x7ffff660b18b
2 __GI_abort abort.c 79 0x7ffff65ea859
3 __libc_message libc_fatal.c 155 0x7ffff66553ee
4 malloc_printerr malloc.c 5347 0x7ffff665d47c
5 _int_free malloc.c 4266 0x7ffff665ede5
6 Eigen::internal::aligned_free Memory.h 177 0x555555564e14
7 Eigen::internal::conditional_aligned_free<true> Memory.h 230 0x55555556601e
8 Eigen::internal::conditional_aligned_delete_auto<float, true> Memory.h 416 0x555555565820
9 Eigen::DenseStorage<float, -1, -1, 1, 0>::~DenseStorage DenseStorage.h 542 0x555555565281
10 Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1>>::~PlainObjectBase PlainObjectBase.h 98 0x5555555650be
11 Eigen::Matrix<float, -1, 1, 0, -1, 1>::~Matrix Matrix.h 178 0x5555555650de
12 main main.cpp 26 0x555555564b42
我以为是因为析构函数是在一个空对象上调用的,但是当我注释掉那行时
// cudaMemcpy(&result, vectorCuda, sizeInBytes, cudaMemcpyKind::cudaMemcpyDeviceToHost);
错误消失了。
那么如何解决呢?
另外,我最近在用 Cuda 编写代码,我的代码中可能有一些错误的行。因此,如果更有经验的人注意到可能导致未来错误的东西,我会很高兴。我想在堆栈中存储开始和结束动态特征向量。
解决此问题的最简单方法是使用 Eigen data() 函数将其转换为 float* 指针,该函数 returns 是指向矩阵中数据的原始指针。您可以将数据传输到 GPU,在那里进行处理,然后将该数据复制回来并再次将其存储在一个漂亮的特征矩阵中。
#include <iostream>
#include <cuda_runtime.h>
#include <eigen3/Eigen/Core>
#include <eigen3/Eigen/Dense>
using Vector = Eigen::Matrix<float, Eigen::Dynamic, 1, Eigen::ColMajor>;
int main(){
Vector vector;
uint64_t size = 6;
vector.resize(size);
for (uint64_t i = 0; i < size; ++i)
vector[i] = i;
uint64_t sizeInBytes = size * sizeof (float);
float *raw_vector = vector.data();
float *vectorCuda;
cudaMalloc((void**)&vectorCuda, sizeInBytes);
cudaMemcpy(vectorCuda, raw_vector, sizeInBytes, cudaMemcpyKind::cudaMemcpyHostToDevice);
Vector result;
result.resize(size);
cudaMemcpy(result.data(), vectorCuda, sizeInBytes, cudaMemcpyKind::cudaMemcpyDeviceToHost);
cudaFree(vectorCuda);
std::cout << "result: " << std::endl << result << std::endl;
return 0;
}
我将学习如何将动态特征向量传输到 GPU 并将其取回。为此,我写了一段测试代码:
using Vector = Eigen::Matrix<float, Eigen::Dynamic, 1, Eigen::ColMajor>;
Vector vector;
uint64_t size = 6;
vector.resize(size);
for (uint64_t i = 0; i < size; ++i)
vector[i] = i;
uint64_t sizeInBytes = size * sizeof (float) + sizeof (vector);
Vector *vectorCuda;
cudaMalloc((void**)&vectorCuda, sizeInBytes);
cudaMemcpy(vectorCuda, &vector, sizeInBytes, cudaMemcpyKind::cudaMemcpyHostToDevice);
Vector result;
result.resize(size);
cudaMemcpy(&result, vectorCuda, sizeInBytes, cudaMemcpyKind::cudaMemcpyDeviceToHost);
cudaFree(vectorCuda);
std::cout << "result: " << std::endl << result << std::endl;
输出为:
result:
0
1
2
3
4
5
double free or corruption (fasttop)
所以我将数据传递给 GPU 并将其取回,但我收到了 SIGABRT 错误。错误发生在std::free(ptr):
1 __GI_raise raise.c 50 0x7ffff660b18b
2 __GI_abort abort.c 79 0x7ffff65ea859
3 __libc_message libc_fatal.c 155 0x7ffff66553ee
4 malloc_printerr malloc.c 5347 0x7ffff665d47c
5 _int_free malloc.c 4266 0x7ffff665ede5
6 Eigen::internal::aligned_free Memory.h 177 0x555555564e14
7 Eigen::internal::conditional_aligned_free<true> Memory.h 230 0x55555556601e
8 Eigen::internal::conditional_aligned_delete_auto<float, true> Memory.h 416 0x555555565820
9 Eigen::DenseStorage<float, -1, -1, 1, 0>::~DenseStorage DenseStorage.h 542 0x555555565281
10 Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1>>::~PlainObjectBase PlainObjectBase.h 98 0x5555555650be
11 Eigen::Matrix<float, -1, 1, 0, -1, 1>::~Matrix Matrix.h 178 0x5555555650de
12 main main.cpp 26 0x555555564b42
我以为是因为析构函数是在一个空对象上调用的,但是当我注释掉那行时
// cudaMemcpy(&result, vectorCuda, sizeInBytes, cudaMemcpyKind::cudaMemcpyDeviceToHost);
错误消失了。
那么如何解决呢?
另外,我最近在用 Cuda 编写代码,我的代码中可能有一些错误的行。因此,如果更有经验的人注意到可能导致未来错误的东西,我会很高兴。我想在堆栈中存储开始和结束动态特征向量。
解决此问题的最简单方法是使用 Eigen data() 函数将其转换为 float* 指针,该函数 returns 是指向矩阵中数据的原始指针。您可以将数据传输到 GPU,在那里进行处理,然后将该数据复制回来并再次将其存储在一个漂亮的特征矩阵中。
#include <iostream>
#include <cuda_runtime.h>
#include <eigen3/Eigen/Core>
#include <eigen3/Eigen/Dense>
using Vector = Eigen::Matrix<float, Eigen::Dynamic, 1, Eigen::ColMajor>;
int main(){
Vector vector;
uint64_t size = 6;
vector.resize(size);
for (uint64_t i = 0; i < size; ++i)
vector[i] = i;
uint64_t sizeInBytes = size * sizeof (float);
float *raw_vector = vector.data();
float *vectorCuda;
cudaMalloc((void**)&vectorCuda, sizeInBytes);
cudaMemcpy(vectorCuda, raw_vector, sizeInBytes, cudaMemcpyKind::cudaMemcpyHostToDevice);
Vector result;
result.resize(size);
cudaMemcpy(result.data(), vectorCuda, sizeInBytes, cudaMemcpyKind::cudaMemcpyDeviceToHost);
cudaFree(vectorCuda);
std::cout << "result: " << std::endl << result << std::endl;
return 0;
}