Как можно одновременно запускать задачи на процессоре и на устройстве с графическим процессором?

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

#pragma omp parallel for schedule(dynamic)
for (int i = 0; i < numberOfTasks; ++i)
{
result[i] = RunTask(i); // result is some array where I store the result of RunTask.
}

Просто так получилось, что RunTask() По сути, это набор операций линейной алгебры, которые каждый раз работают с одним и тем же очень большим набором данных, поэтому он подходит для работы на GPU. Поэтому я хотел бы добиться следующего:

  1. Переложить некоторые задачи на графический процессор
  2. Пока GPU занят, выполняйте остальные задачи на CPU
  3. Для операций на уровне процессора, держите мой супер RunTask() функция без необходимости изменять его в соответствии с restrict(amp), Я мог бы, конечно, разработать restrict(amp) совместимая лямбда для задач GPU.

Первоначально я думал сделать следующее:

// assume we know exactly how much time the GPU/CPU needs per task, and this is the
// most time-efficient combination:
int numberOfTasks = 1000;
int ampTasks = 800;

// RunTasksAMP(start,end) sends a restrict(amp) kernel to the GPU, and stores the result in the
// returned array_view on the GPU
Concurrency::array_view<ResulType, 1> concurrencyResult = RunTasksAMP(0,ampTasks);

// perform the rest of the tasks on the CPU while we wait
#pragma omp parallel for schedule(dynamic)
for (int i = ampTasks; i < numberOfTasks; ++i)
{
result[i] = RunTask(i); // this is a thread-safe
}

// do something to wait for the parallel_for_each in RunTasksAMP to finish.
concurrencyResult.synchronize();
//... now load the concurrencyResult array into the first elements of "result"

Но я сомневаюсь, что вы могли бы сделать что-то подобное, потому что

Вызов функции parallel_for_each ведет себя так, как если бы он был синхронным

(http://msdn.microsoft.com/en-us/library/hh305254.aspx)

Так можно ли выполнить 1-3 моих запроса, или я должен отказаться от номера 3? Тем не менее, как бы я это реализовал?

5

Решение

Смотрите мой ответ на будет ли array_view.synchronize_asynch ждать завершения parallel_for_each? для объяснения того, почему parallel_for_each может быть как операция очередей или планирования, а не синхронная. Это объясняет, почему ваш код должен удовлетворять вашим требованиям 1 & 2. Он также должен соответствовать требованию 3, хотя вы можете рассмотреть возможность использования одной функции, которая restrict(cpu, amp) так как это даст вам меньше кода для поддержки.

Однако вы можете рассмотреть некоторые последствия для вашего подхода к производительности.

Во-первых, parallel_for_each работают только очереди, копии данных с хоста и памяти GPU используют ресурсы хоста (при условии, что ваш GPU дискретен и / или не поддерживает прямое копирование). Если ваша работа на хосте насыщает все ресурсы, необходимые для работы графического процессора, вы можете фактически замедлить вычисление графического процессора.

Во-вторых, для многих вычислений, которые являются параллельными данными и поддаются выполнению на графическом процессоре, они настолько быстры, что дополнительные накладные расходы при попытке запустить работу на процессоре не приводят к общему ускорению. Служебные расходы включают первый элемент (выше) и дополнительные накладные расходы на координацию работы на хосте (планирование потоков, объединение результатов и т. Д.).

Наконец, ваша реализация выше не учитывает какую-либо изменчивость во времени, затрачиваемом на выполнение задач на GPU и CPU. Предполагается, что задачи 800 AMP будут занимать до 200 задач процессора. Это может быть верно на некоторых аппаратных средствах, но не на других. Если один набор задач занимает больше времени, чем ожидалось, тогда ваше приложение заблокируется и будет ожидать завершения более медленного набора задач. Вы можете избежать этого, используя шаблон мастер / работник для извлечения задач из очереди, пока не останется больше доступных задач. Этот подход означает, что в худшем случае вашему приложению придется ждать завершения конечной задачи, а не блока задач. Использование подхода мастер / работник также означает, что ваше приложение будет работать с одинаковой эффективностью независимо от относительной производительности ЦП / ГП.

Моя книга обсуждаются примеры планирования работы для нескольких графических процессоров с использованием master / worker (n-body) и параллельной очереди (cartoonizer). Вы можете скачать исходный код с CodePlex. Обратите внимание, что он намеренно не охватывает совместную работу на процессорах и графических процессорах по причинам, изложенным выше, на основе обсуждений с командой разработчиков C ++ AMP.

4

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

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector