Ручная раскрутка петли с известным максимальным размером
Пожалуйста, посмотрите на этот код в ядре OpenCL:
uint point_color = 4278190080;
float point_percent = 1.0f;
float near_pixel_size = (...);
float far_pixel_size = (...);
float delta_pixel_size = far_pixel_size - near_pixel_size;
float3 near = (...);
float3 far = (...);
float3 direction = normalize(far - near);
point_position = (...) + 10;
for (size_t p = 0; p < point_count; p++, position += 4)
{
float3 point = (float3)(point_list[point_position], point_list[point_position + 1], point_list[point_position + 2]);
float projection = dot(point - near, direction);
float3 projected = near + direction * projection;
float rejection_length = distance(point, projected);
float percent = projection / segment_length;
float pixel_size = near_pixel_size + percent * delta_pixel_size;
bool is_candidate = (pixel_size > rejection_length && point_percent > percent);
point_color = (is_candidate ? (uint)point_list[point_position + 3] | 4278190080 : point_color);
point_percent = (is_candidate ? percent : point_percent);
}
Этот код пытается найти точку в списке, которая является ближайшей к отрезку линии между дальним и ближним, и назначая ее цвет для point_color и ее "процентное расстояние" для point_percent. (Кстати, код вроде бы в порядке).
Число элементов, указанное в point_count, является переменным, поэтому я не могу слишком много предполагать, за исключением одного: point_count всегда будет равен или меньше 8. Это фиксированный факт в моем коде и данных.
Я хотел бы развернуть этот цикл вручную, и я боюсь, что мне нужно будет использовать много
value = (point_count < constant ? new_value : value)
для всех строк в нем. По вашему опыту, увеличит ли такая стратегия производительность моего ядра?
И да, я знаю, я должен сам провести некоторый тест; Я просто хотел спросить кого-то с большим опытом в OpenCL, прежде чем пытаться сделать это самостоятельно.
1 ответ
Большинство драйверов OpenCL (с которыми я знаком, по крайней мере) поддерживают использование #pragma unroll
развернуть циклы во время компиляции. Просто используйте это так:
#pragma unroll
for (int i = 0; i < 4; i++) {
/* ... */
}
Это практически то же самое, что развернуть его вручную без каких-либо усилий. В вашем случае это будет выглядеть примерно так:
if (pointCount == 1) {
/* ... */
} else if (pointCount == 2) {
#pragma unroll
for (int i = 0; i < 2; i++) { /* ... */ }
} else if (pointCount == 3) {
#pragma unroll
for (int i = 0; i < 3; i++) { /* ... */ }
}
Я не могу точно сказать, будет ли улучшение, но есть один способ узнать. Если pointCount
например, постоянная для локальной рабочей группы, это может улучшить производительность, но если она полностью переменная, это может даже ухудшить ситуацию.
Вы можете прочитать больше об этом здесь.