Как узнать размер динамического собственного вектора в байтах?

#c #size #eigen #sizeof #eigen3

#c #размер #eigen #sizeof #eigen3

Вопрос:

Я собираюсь вычислить размер вектора. Если я напишу этот код:

     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), но не уверен, что это правильный вариант. Итак, что мне нужно?

Комментарии:

1. sizeof — это оператор времени компиляции. Вы не можете получить реальный размер с его помощью. Если вы знаете размер (количество элементов) в векторе, почему вы не можете получить размер?

2. Спасибо за ваш комментарий. На самом деле этот вопрос является частью более сложного вопроса, который я задам в stackoverflow чуть позже. Реальная причина этой ситуации заключается в том, что я пытаюсь передать динамический вектор на графический процессор с помощью Cuda. И получение некоторых ошибок в cudaMemcpy, скорее всего, связанных с вычислением размера объекта.

Ответ №1:

Если 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); }
}; 
 

О проблеме в комментарии:

Я пытаюсь передать динамический вектор на графический процессор с помощью 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));
}
 

Комментарии:

1. Спасибо за такой подробный ответ. Если я правильно понял ваш ответ, мое предположение с «sizeof (float) * vector.size () sizeof (vector)» было правильным. Я не был уверен, что данные * являются единственной частью объекта, хранящегося в куче. И спасибо за совет выделить весь объект в куче. Я не думаю, что это спасет меня сейчас, но это определенно может помочь позже.

2. Да, вы были правы. При этом, даже получив размер вектора, вы все равно не сможете его переместить, потому что он не является непрерывным. И даже если бы это было так, адрес data , на который указывает, был бы признан недействительным. Кроме того, вектор зависит от реализации, поэтому он не обязательно структурирован таким образом (думал, что, скорее всего, так и должно быть).