2016-01-08 3 views
0

Предположим, я хочу вычислить поднятый косинус. Я мог бы иметь макрос, который делает #define cos_raised(x) (0.5f + 0.5f * cos(x)), но ради моей проблемы, я хочу, чтобы сделать его функцию, например:Векторизация моей скалярной функции

float cos_raised(float x) 
{ 
    return 0.5f + 0.5f * cos(x); 
} 

Это прекрасно работает, но только с одним входом поплавка, когда он может быть легко vectorised. Как правильно его апроксировать и заставить его принимать float2/3/4/8/16 как вход и выход без дублирования тела функции (это тривиальный пример, но мне нужно знать это для более сложных функций)?

Редактировать: Я думаю, я спрашиваю, как сделать функцию gentype? Просто набрав gentype, не работает.

+0

Будет ли в вашем ядре одна версия 'cos_raised' или несколько версий, то есть одновременно с версией' float2' и 'float4'? Если всегда будет только одна версия, определив несколько макросов при создании ядра. – chippies

+0

Какие макросы? Идея состоит в том, чтобы иметь одну версию, но работать с этими разными типами. –

+1

Что я имел в виду, скажем, ваше ядро ​​использует только версию 'float cos_raised (floatN x)', но вы не знаете, что такое 'floatN', пока ваша программа не будет запущена. Этот сценарий применим, когда вы векселируете все свои функции для работы с той же шириной вектора, но ширина вектора определяется только во время выполнения. Если это так, вы можете использовать параметр 'options'' clBuildProgram' и передать что-то вроде '' -D floatN = float2''. Таким образом, у вас есть одна версия функции в вашем коде, и она будет работать, с которой когда-либо вводится тип 'floatN'. Достаточно ли этого? – chippies

ответ

0

IIRC: К сожалению, «gentype» - это концепция, которая существует только в документации OpenCL, это не функция языка, которая позволяет вам создавать общие/templatelike функции самостоятельно. Это означает, что нет простого способа сделать то, что вы хотите, и вам, вероятно, придется работать над препроцессорной магией, чтобы свести к минимуму дублирование кода. См. этот поток SO: How to use C++ templates in OpenCL kernels?, который предлагает больше знаний, чем я мог.

0

Если компилятор строит все ваши вызовы функций до того, как он выполнит векторизацию, тогда вы все настроены. Кстати, векторизация, вероятно, необходима только для выполнения ЦП, поскольку большинство графических процессоров теперь являются скалярными.

+0

Как? Поскольку это просто кормление cos_raised() с помощью float4, невозможно скомпилировать. –

+0

Извините, я не понимаю ваш вопрос. Пожалуйста, переустановите его. – Dithermaster

+0

Как я могу установить? Что мне нужно сделать, чтобы он работал так? Потому что, поскольку он не компилируется. –

0

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

float{N:} cos_raised_float{N:}(float{N:} x) 
{ 
    return 0.5f + 0.5f * cos(x); 
} 

Поскольку я больше знакомы с Python, я использовал это синтаксис для указания заполнителей в строка, то есть {N:}. Вам нужно будет найти что-то подобное для вашего языка хост-кода. После этого просто пропустите петлю, проходящую через 2, 3, 4, 8 и 16, каждый раз, заполняя {N:}. Это дает вам пять дополнительных строк, которые необходимо добавить в начало кода ядра. Нижняя сторона заключается в том, что вам придется каким-то образом указать в главном коде ядра, где все эти сгенерированные функции должны быть вставлены. Они должны появиться после всех операторов #pragma XXX: enable. Впоследствии ваше ядро ​​может вызывать любую версию, например. cos_raised_float4.

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