Различают память на стороне хоста и на стороне устройства
В качестве другого ответа также укажите:
- Память GPU (глобальная), которую вы выделяете с помощью
cudaMalloc()
, недоступна по коду, работающему на CPU;и - Системная память (она же memorY хоста), которую вы выделяете в простом C ++ (с
std::vector
, с std::make_unique
, с new
и т. д.), недоступна из-за кода, работающего наGPU.
Итак, вам нужно выделить память как на стороне хоста, так и на стороне устройства.Простой пример работы с памятью как на стороне устройства, так и на стороне хоста см. В примере программы CUDA vectorAdd
.
(На самом деле вы также можете сделать специальный видраспределения, который является доступным как с устройства, так и с хоста, это Unified Memory . Но давайте пока проигнорируем это, поскольку мы имеем дело с основами.)
Не живите в царстве существительных
В частности, я хочу выделить память на устройстве для поплавков в конструкторе классов, а затем освободить ее в деструкторе.
Я не уверен, что вы действительно хотите это сделать.Похоже, вы придерживаетесь подхода Java-esque, в котором все, что вы делаете, ориентировано на существительное, то есть классы используются для всего: вы не решаете уравнения, у вас есть «решатель уравнений».Вы не «делаете X», у вас есть класс «XDoer» и т. Д. Почему бы просто не иметь (шаблонную) функцию, которая решает систему ODE, возвращая решение?Используете ли вы «решатель» каким-либо другим способом?
(этот момент вдохновлен постом Стива Йегге в блоге, Казнь в царстве существительных .)
Попробуйтечтобы избежать выделения и перераспределения себя
В хорошо написанном современном C ++ мы стараемся избегать прямого, ручного выделения памяти (кстати, это ссылка на Руководство по программированию C ++ Core).).Это правда, что вы освобождаете свою память деструктором, так что это не так уж и плохо, но я бы действительно подумал об использовании std::unique_ptr
на хосте и что-то эквивалентное на устройстве (например, cuda::memory::unique_ptr
из моей оболочки API Modern-C ++ CUDA cuda-api-wrappers
библиотека);или GPU-ориентированный класс контейнера, такой как thrust
вектор устройства.
Проверка на ошибки
Вы действительно должны проверить на ошибки послеВы вызываете функции API CUDA.И это вдвойне необходимо после запуска ядра.Когда вы вызываете код стандартной библиотеки C ++, он выдает исключение при ошибке;API CUDA во время выполнения похож на C и не знает об исключениях.Он просто потерпит неудачу и установит некоторую переменную ошибки, которую нужно проверить.
Итак, вы либо пишете проверки ошибок, как в примере vectorAdd()
, с которым я ссылался выше, либо вы получаете какую-то библиотеку для демонстрации более стандартныхбиблиотечно-подобное поведение.cuda-api-wrappers
и thrust
оба сделают это - на разных уровнях абстракции;как и другие библиотеки / фреймворки.