2013-09-13 5 views
0

Мое ядро ​​довольно простое. Он пытается увидеть, если коды являются действительными, а затем сохраняют только уникальные коды в соответствии с выходными сканирования приставки:OpenCL - ядро ​​работает медленно

__kernel void moveValid(__global int* sortCode, __global int* mark, __global int* processorOffsets, __global int* uniqueCode,__global int* numPoints, __global int* pointIndex) 
{ 
    int ig = get_global_id(0); 
    int m = mark[ig]; 
    int j= processorOffsets[ig]; 
    atomic_inc(&numPoints[j-1]); 
    // select 
    if(m == true) 
    { 
      uniqueCode[j] = sortCode[ig]; 
      pointIndex[j] = ig; 
    } 

    barrier(CLK_GLOBAL_MEM_FENCE); 
} 

Похоже, что ядро ​​очень медленно. Это связано с утверждением if? Может ли кто-нибудь дать советы о том, как можно улучшить ядро? Также можно выбрать использование в этом сценарии?

ответ

2

Итак, не задумываясь над своим кодом, я могу дать следующую информацию о его скорости. Я предполагаю, что вы используете GPU в качестве своего устройства. Если вы используете процессор в качестве своего устройства, некоторые из них могут по-прежнему применяться.

atomic_inc (& numPoints [j-1]);

Атомные приращения на большинстве аппаратов PAINFULLY медленны в глобальной памяти. Это связано с тем, что данные должны быть переданы в глобальную память (они не могут быть кэшированы локально).

барьер (CLK_GLOBAL_MEM_FENCE);

Этот барьер гарантирует, что все рабочие_иденения в рабочей_группе присутствуют перед продолжением выполнения. Зачем вам это нужно в коде? Особенно, когда ничего не остается делать, нет причин не позволять вашим потокам завершить выполнение. Это также большой успех.

если (м == верно)

Это на самом деле не самое худшее, если заявление, которое я видел, потому что он имеет только одну ветвь. Это все равно замедлит ваш код, но не так существенно, как другие. Условие будет вычислено для всех потоков в серийном (для некоторых архитектур), прежде чем продолжить.

В целом, в этом коде вы выполняете 4 глобальных доступа к памяти, как при атомной операции, так и без математических операций. Графические процессоры являются наихудшим типом устройства для выполнения этого типа алгоритма, поскольку обращения к памяти исключительно медленны для глобальной памяти, особенно если соединения объединены. Не могли бы вы переместить некоторые из ваших массивов в локальную память?

+0

спасибо. Я все еще не совсем уверен, где поставить барьер в ядро ​​и когда. Я изменил atom_inc на локальную память. Ядро работает быстрее. – shunyo

+0

Обычно вам не нужен барьер. Барьеры будут необходимы только тогда, когда вы выполняете работу, а затем хотите дождаться своей рабочей_группы, а затем выполните больше работы. Кроме того, вполне вероятно, что барьер не работает так, как вы думаете. Если вам нужен глобальный барьер (например, тот же объем работы, выполняемый каждой рабочей группой), то делайте это через выполнение ядра вместо использования барьера. Также убедитесь, что вы понимаете различия между различными воспоминаниями (глобальными, локальными, частными), а не просто используете их. – KLee1

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