Есть большой массив чисел ([math]2^{21}[/math] штук). Нужно найти такое же количество совпадений чисел в этом массиве (на самом деле их больше, но все не нужны). Решаю задачу на OpenCL следующим образом: создаю [math]2^{21}[/math] потоков, каждому соответствует одно из чисел, и сравниваю в каждом потоке это число с остальными (так, чтобы n-ое число с m-ым сравнивалось 1 раз) и в случае совпадения записываю пары индексов в выходной массив. Для доступа к массиву использую атомарные операции (см. Shader.cl в приложении). Запускаю код на моей карте GeForce GT 750M, всё вроде бы нормально, но при попытке чтения результата (clEnqueueReadBuffer) возвращается CL_OUT_OF_RESOURCES (хотя clCreateBuffer работает нормально). Если удалить код, пишущий в массив вместе atomic_cmpxchg, то ошибка проподает, как собственно и результат. Что мне с этим делать? ОС Win10 x64, карта GeForce GT 750M ноутбук.
зачем вам тут атомики? каждый тред = индексу елемента в новом выходном массиве, ничего не перекрывается.
А если один тред найдёт несколько совпадений? Если например все числа кроме одного будут одинаковыми? На самом деле я не совсем верно написал условие: искать я буду все совпадения, просто порциями.
_qwe8013, правильное решение данной задачи: к каждому элементу цепляем его индекс и сортируем получившиеся пары по значениям на выходе получаем массив в котором элементы с одинаковыми значением будут рядом ну и соответственно далее можно записать это в файл в виде таких строк: имеется N элементов со значением X, индексы у них i1 i2 i3 ... имеется M элементов со значением Y индексы у них j1 j2 j3 ... кому будет нужно легко по этим строкам построит все возможные пары индексов
Есть AVL деревья для быстрого поиска, это и должно использоваться, раз массив не линеен. Зачем нужны атомики представить сложно.
Буду делать с помощью сортировки, спасибо за ответы. PS Раз уж речь зашла об атомиках, они вообще как-либо серьёзно влияют на производительность?
_qwe8013, да, очень серьезно. Надо стараться их избегать. Особенно когда идет работа не с шаред мемори и с оч большим кол-вом потоков, где нельзя спрогнозировать, как много будет коллизий.
В общем последовал совету и стал сначала сортировать. Написал алгоритм сортировки на OpenCL и продублировал его на CPU. Так вот, начиная с размера массива [math]2^{12}[/math] алгоритм на OpenCL начинает выдавать некорректный результат (результат не отсортирован) на любом OpenCL устройстве, хотя CPU отрабатывает корректно. Ткните идиота в ошибку.
В общем выяснил, что в шейдере в цикле по переменной "i" В КОНЦЕ КОТОРОГО СТОИТ barrier(CLK_GLOBAL_MEM_FENCE) почему-то некоторые потоки исполняют первую итерацию когда другие исполняют ещё только нулевую WTF?