#c #cuda #eigen #eigen3 #gpu
#c #cuda #eigen #eigen3 #графический процессор
Вопрос:
Я собираюсь узнать, как передать динамический собственный вектор на графический процессор и получить его обратно. Для этих целей я написал тестовый код:
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**)amp;vectorCuda, sizeInBytes);
cudaMemcpy(vectorCuda, amp;vector, sizeInBytes, cudaMemcpyKind::cudaMemcpyHostToDevice);
Vector resu<
result.resize(size);
cudaMemcpy(amp;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(amp;result, vectorCuda, sizeInBytes, cudaMemcpyKind::cudaMemcpyDeviceToHost);
ошибка исчезла.
Итак, как это исправить?
Кроме того, я пишу на Cuda совсем недавно, и в моем коде могут быть некоторые неправильные строки. Поэтому я был бы рад, если бы кто-то более опытный заметил что-то, что может вызвать будущие ошибки. Я хотел бы сохранить начальный и конечный динамические собственные векторы в стеке.
Ответ №1:
Самый простой способ исправить это — превратить это в указатель с плавающей точкой * с помощью функции Eigen data(), которая возвращает необработанный указатель на данные в вашей матрице. Вы можете перенести данные на графический процессор, поработать с ними там, затем скопировать эти данные обратно и снова сохранить их в хорошей собственной матрице.
#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**)amp;vectorCuda, sizeInBytes);
cudaMemcpy(vectorCuda, raw_vector, sizeInBytes, cudaMemcpyKind::cudaMemcpyHostToDevice);
Vector resu<
result.resize(size);
cudaMemcpy(result.data(), vectorCuda, sizeInBytes, cudaMemcpyKind::cudaMemcpyDeviceToHost);
cudaFree(vectorCuda);
std::cout << "result: " << std::endl << result << std::endl;
return 0;
}
Комментарии:
1. Спасибо за ваш ответ. Возможно, мой вопрос был не совсем полным. Я искал способ отправить динамический собственный вектор в ядро, потому что некоторые функции внутри ядра используют его. К сожалению, я пришел к выводу, что единственный способ — передать данные на GPU в виде указателя с плавающей точкой * из data(), а затем обернуть их внутри ядра с помощью Eigen::Map.
2. Это, вероятно, довольно хорошее решение, т.е., Может быть, не самое элегантное, но вызов eigen::map внутри ядра (или функции вызова), вероятно, не приведет к значительным накладным расходам.