Я собираюсь вычислить размер вектора. Если я напишу этот код:
Eigen::Matrix<float, 6, 1, Eigen::ColMajor> staticVector;
std::cout << "sizeInBytes: " << sizeof (staticVector) << std::endl;
вывод:
sizeInBytes: 24
Но если я напишу:
Eigen::Matrix<float, Eigen::Dynamic, 1, Eigen::ColMajor> dynamicVector;
dynamicVector.resize(6);
std::cout << "sizeInBytes: " << sizeof (dynamicVector) << std::endl;
вывод:
sizeInBytes: 16
Хорошо, sizeof (vector) не показывает реальный размер динамического вектора. Что я должен использовать? Я бы попробовал sizeof (float) * vector.size() или sizeof (float) * vector.size() + sizeof (vector), но не уверен, что это правильный вариант. Итак, что мне нужно?
Спасибо за ваш комментарий. Этот вопрос на самом деле является частью более сложного вопроса, который я задам чуть позже в stackoverflow. Настоящая причина такой ситуации в том, что я пытаюсь передать динамический вектор на GPU с помощью Cuda. И получение некоторых ошибок в cudaMemcpy, скорее всего, связанных с вычислением размера объекта.
Если весь массив Eigen::Matrix
находится в стеке, то sizeof
должен вернуть правильное значение. Это было бы здорово для небольших матриц, но могло бы стать опасным для больших, так как могло бы вызвать переполнение стека.
Если данные хранятся в куче, вам нужно создать метод, который добавляет память стека и кучи и возвращает ее. Это был бы возможный пример:
template<class T, size_t ROWS, size_t COLS, Eigen::SomeEnumType>
class Matrix {
// ...
private:
std::array<std::array<T, COLS>, ROWS> *data;
public:
Matrix() { data = new std::array<std::array<T, COLS>, ROWS>(); }
// Assumes all dynamically allocated memory is the data.
size_t sizeInBytes() const { return sizeof(T) * ROWS * COLS + sizeof(*this); }
};
По поводу беспокойства в комментарии:
Я пытаюсь передать динамический вектор на GPU с помощью Cuda
Я очень мало работал с CUDA, поэтому могу ошибаться, но IIRC — единственный способ передать что-то на GPU с помощью memcpy
-подобной операции. Это было бы очень трудно или даже невозможно для векторов, которые содержат данные как стека, так и кучи далеко друг от друга. Лучшим способом было бы разместить все данные внутри объекта (чтобы они были непрерывными в памяти), а затем, если вы боитесь переполнения стека, просто выделить весь объект в куче:
template<class T, size_t ROWS, size_t COLS, Eigen::SomeEnumType>
class Matrix {
// ...
std::array<std::array<T, COLS>, ROWS> data;
};
int main() {
auto *mat = new Eigen::Matrix<float, 6, 1, Eigen::ColMajor>(...);
void *GPU_mat = malloc_GPU(sizeof(*mat));
memcpy_to_GPU(GPU_mat, mat, sizeof(*mat));
}
Спасибо за такой подробный ответ. Если я правильно понял ваш ответ, моя догадка с «sizeof (float) * vector.size () + sizeof (vector)» была правильной. Я не был уверен, являются ли *data единственной частью объекта, хранящегося в куче. И спасибо за совет разместить весь объект в куче. Не думаю, что это спасет меня сейчас, но определенно может помочь позже.
Да, ты был прав. При этом, даже получив размер вектора, вы все равно не сможете его переместить, потому что он не является смежным. И даже если бы это было так, адрес, на который указывает data
, был бы признан недействительным. Кроме того, вектор зависит от реализации, поэтому он не обязательно структурирован таким образом (хотя, скорее всего, так и должно быть).
sizeof — это оператор времени компиляции. Вы не можете получить реальный размер с ним. Если вы знаете размер (количество элементов) в векторе, почему вы не можете получить размер?