2014-10-12 2 views
0

У меня есть ядро, которое выполняет две задачи, А затем В.сериализовать рабочие элементы группы в ядре

A распараллеливаются над всеми рабочими элементами, и В являются очень последовательным, так что только первым рабочим элемент выполняет его ,

Каждый рабочий элемент может выполнять часть B, если я могу заставить их выполнить последовательность. Это двумерное ядро, и я хотел бы, чтобы рабочие элементы выполнялись в растровом шаблоне.

Возможно ли это? Одна из идей - это локальная переменная, которую могут обрабатывать все рабочие элементы, а рабочий элемент , который соответствует переменной, будет выполнять и изменять переменную, чтобы она запускала следующий рабочий элемент.

Любые идеи/шаблоны о том, как это сделать?

Спасибо!

Edit:

Вот некоторые псевдо код, как в настоящее время работает моя ядро:

void myKernel(void) { 

    // perform A task (all work items are active) 

    barrier(CLK_LOCAL_MEMORY_FENCE); 

    if (get_local_id(0) == 0 && get_local_id(1) == 0) { 
     //perform task B 
    } 

} 

и вот как мне хотелось бы, чтобы работать:

// 10 x 10 2D kernel 
void myKernel(void) { 

    // perform A task (all work items are active) 

    barrier(CLK_LOCAL_MEMORY_FENCE); 

    local activeIndex =0; 
    while (activeIndex < 100) { 
     if (get_local_id(0) + 10* get_local_id(1) == activeIndex) { 
      // perform part of task B 
      activeIndex++; 
     } 
     barrier(CLK_LOCAL_MEMORY_FENCE); 
    } 
    } 
} 

Edit 2: Я пробовал этот код на своем HD 7700, но он был очень медленным. Наверное, я буду придерживаться локальной памяти.

+0

У вас есть пример кода, чтобы показать нам? Ваш вопрос довольно расплывчатый. Что такое B? Многие алгоритмы могут быть эффективно распараллелены, даже если это не всегда очевидно. –

+0

Спасибо, Cicada. Задача B представляет собой арифметический кодер, где состояние кодера в заданном пикселе зависит от предыдущего пикселя и т. Д. Таким образом, он действительно не может быть распараллелен. – Jacko

ответ

0

Вы можете делать то, что вы описываете, для каждой рабочей группы. Барьеры предоставят вам необходимую функциональность. Если вы хотите сделать это на глобальном уровне, вам не повезло. Используя переменную, чтобы проверить глобальное состояние, прежде чем возобновлять ядро, известно как «прямая блокировка», и я вызвал несколько ситуаций, связанных с WSOD (белый экран смерти), которые пробовали это для себя.

Там нет ничего плохого в коде примера вы в курсе, за исключением может быть отсутствие Params ...

void myKernel(void) { 

    // perform A task (all work items are active) 

    barrier(CLK_LOCAL_MEMORY_FENCE); 

    if (get_local_id(0) == 0 && get_local_id(1) == 0) { 
     //perform task B 
    } 

} 
+0

Спасибо, mfa. Мне просто нужно синхронизировать рабочие элементы в рабочей группе. Наверное, я попробую. – Jacko

0

У вас нет гарантий, что все рабочие элементы «A» будут работать вместе; они могут запускаться партиями. Таким образом, вы не можете делать «B», даже для одного рабочего элемента, в том же ядре, что и «A». Если все рабочие элементы «A» должны заканчиваться до начала «B», «B» должно быть отдельным ядром, которое вы можете запустить с любым глобальным размером работы, самым подходящим для вашей проблемы.

+0

Спасибо. Я добавлю редактирование с помощью некоторого псевдокода. – Jacko

Смежные вопросы