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

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

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

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

tango-1 13.12.2020 18:53

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

Ivanko 13.12.2020 19:03
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
2 186
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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); }
}; 

По поводу беспокойства в комментарии:

Я пытаюсь передать динамический вектор на 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 единственной частью объекта, хранящегося в куче. И спасибо за совет разместить весь объект в куче. Не думаю, что это спасет меня сейчас, но определенно может помочь позже.

Ivanko 13.12.2020 19:23

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

Kostas 13.12.2020 20:34

Другие вопросы по теме