#for-loop #opencl #noise
#для цикла #opencl #шум
Вопрос:
В настоящее время я внедряю генерацию ландшафта в OpenCL, используя многоуровневые октавы шума, и я наткнулся на эту проблему:
float multinoise2d(float2 position, float scale, int octaves, float persistence)
{
float result = 0.0f;
float sample = 0.0f;
float coefficient = 1.0f;
for(int i = 0; i < octaves; i ){
// get a sample of a simple signed perlin noise
sample = sgnoise2d(position/scale);
if(i > 0){
// Here is the problem:
// Implementation A, this works correctly.
coefficient = pown(persistence, i);
// Implementation B, using this only the first
// noise octave is visible in the terrain.
coefficient = persistence;
persistence = persistence*persistence;
}
result = coefficient * sample;
scale /= 2.0f;
}
return resu<
}
OpenCL распараллеливает for-циклы, что приводит к проблемам синхронизации здесь, или я что-то еще упускаю?
Любая помощь приветствуется!
Комментарии:
1. где этот код использует OpenCL? OpenCL не распараллеливает for-циклы. Вам нужно написать код, используя поток / блоки.
2. @Vivek G: некоторые компиляторы OpenCL могут автоматически изменять вектор для циклов.
3. @Anselm: Вы предполагаете, что разделение pown на два отдельных оператора является потенциальной угрозой синхронизации? Но pown — это не атомарная функция; у нее тоже могут быть проблемы с синхронизацией. Но, как сказал Джеймс ниже, вся ваша память является частной для рабочего элемента, поэтому это спорный вопрос.
Ответ №1:
проблема вашего кода в строках
coefficient = persistence;
persistence = persistence*persistence;
Это должно быть изменено на
coefficient = coefficient *persistence;
в противном случае на каждой итерации
первый коэффициент увеличивается только за счет постоянства
pow(persistence, 1) ; pow(persistence, 2); pow(persistence, 3) ....
Однако вторая реализация идет
pow(persistence, 1); pow(persistence, 2); pow(persistence, 4); pow(persistence, 8) ......
вскоре «постоянство» превысит предел для float, и вы получите нули (или неопределенное поведение) в своем ответе.
ОТРЕДАКТИРУЙТЕ еще две вещи
- Накопление (реализация 2) — не очень хорошая идея, особенно с действительными числами и алгоритмами, которые требуют точности. Возможно, вы теряете небольшую часть вашей информации каждый раз, когда вы накапливаете «постоянство» (например, из-за округления). Предпочитайте прямое вычисление (1-я реализация), а не накопление, когда можете. (плюс, если это было последовательным, 2-я реализация будет легко распараллеливаемой.)
- Если вы работаете с AMD OpenCL, обратите внимание на функции pow(). У меня неоднократно возникали проблемы с ними на нескольких машинах. Функции, кажется, иногда зависают без причины. Просто К вашему сведению.
Комментарии:
1. Базовая математика снова терпит неудачу. Спасибо и за советы!
Ответ №2:
Я предполагаю, что это какой-то служебный метод, который вызывается в вашем ядре CL. Вивек прав в своем комментарии выше: OpenCL не распараллеливает ваш код за вас. Вы должны использовать возможности OpenCL для разделения вашей проблемы на фрагменты, параллельные данным.
Кроме того, я не вижу потенциальной проблемы синхронизации в приведенном выше коде. Все ваши переменные находятся в личном пространстве памяти рабочего элемента.
Комментарии:
1. хорошо, тогда все в порядке, поскольку я не хочу распараллеливать эту часть кода (и не могу, поскольку постоянные обратные связи). Есть идеи, почему итеративная мощность не работает, но работает pown?