асинхронный — усилитель C ++: асинхронная передача данных и хранение данных на ускорителе

У меня есть часто вызываемая функция, которая отлично подходит для параллельной обработки, поэтому я для начала исследовал усилитель C ++. Функция принимает три входа:

  1. вектор с плавающей точкой, который является входными данными
  2. вектор постоянных коэффициентов, который остается неизменным на протяжении вызовов
  3. выходной вектор, в который записывается результат.

Теперь очевидно, что # 1 должен копироваться в GPU при каждом вызове. Для этого я использую управляемый стеком константный массив<>, который отлично работает.

Для # 2 оптимальным вариантом было бы как-то сохранить вектор в памяти графического процессора, поскольку он постоянен. Возможно ли это с помощью усилителя? Или мне нужно копировать его каждый раз, когда я вызываю параллель_for_each, аналогично # 1?

Для # 3, возможно ли выделить буфер на GPU и скопировать его обратно, вместо создания пустого буфера в стеке процессора, скопировать его и скопировать обратно после записи результатов в него?

И последнее, так как вызов параллелизма в природе является асинхронным — и будет синхронизироваться либо деструктором # 3, либо array_view :: synchronize (), можно ли оставить текущую функцию (и пространство стеков), тем временем сделайте другие вещи GPU обрабатывает, а затем «синхронизируется» на более позднем этапе?

Это потребовало бы динамически распределенного array_view, чтобы избежать синхронизации () при разрушении, но функция, похоже, не будет компилироваться, когда я использую указатели вместо объектов, управляемых стеком:

error C3581: unsupported type in amp restricted code
pointer or reference is not allowed as pointed to type, array element type or data member type (except reference to concurrency::array/texture)

Кроме того, для тех, кто имеет опыт в других архитектурных проектах, таких как OpenCL, мне повезет больше?

2

Решение

1 — Да. Если вы передаете const array_view в качестве ввода он не будет скопирован обратно в память хоста.

std::vector<float> cpu_data(20000000, 0.0f);
array_view<const float, 1> cpu_data_view(cpu_data.size(), cpu_data);

2 — В зависимости от размера вашего массива коэффициентов вы можете сделать одну из нескольких вещей;

а — Храните его в локальном массиве в вашем parallel_for_each лямбда. Это удобно, но потребляет (драгоценную) локальную память, поэтому реалистично, только если массив очень маленький.

array<float, 1> gpu_data(400);
std::vector<float> cpu_data(gpu_data.extent.size(), 1.0f);
copy(cpu_data.begin(), gpu_data);

В этом случае gpu_data будет доступен для всего кода AMP при условии, что лямбда-код перехватывает его.

б — Создать array и явно скопируйте ваши постоянные данные в него перед выполнением любого кода AMP.

с — Рассмотрите возможность загрузки в tile_static памяти, если к нему обращается много раз каждый поток.

3 — Вы все еще можете использовать array_view чтобы сохранить ваши выходные данные, но вызов discard_data на нем до выполнения parallel_for_each предотвратит ненужное копирование в память графического процессора.

std::vector<float> cpu_output_data(20000000, 0.0f);
array_view<float, 1> output_data_view(cpu_output_data.size(), cpu_output_data);
output_data_view.discard_data();

** Async — ** Да, это вполне возможно сделать. Вы можете комбинировать AMP с фьючерсами C ++ и асинхронными операциями для одновременного выполнения другой работы на CPU (или другом GPU). Помните, что ЦП участвует в управлении расписанием работы на GPU и перемещении данных в него и из него. Таким образом, если вы перегружаете процессор, производительность графического процессора может снизиться.

WRT к вашей ошибке компилятора, трудно сказать, в чем проблема, не видя код. Это нормально делать следующее:

std::unique_ptr<concurrency::array_view<int, 2>> data_view;

Возможно, вы захотите взглянуть на примеры, описанные в книге C ++ AMP. Они доступны на CodePlex и охватывают многие из этих сценариев.

3

Другие решения


По вопросам рекламы [email protected]