none
Стек(динамический массив) в parallel_for_each RRS feed

  • Вопрос

  • При работе с функцией parallel_for_each нужно обрабатывать данные различного количества, т.е на входе у меня есть фиксированное количество данных которые обрабатываются в parallel_for_each во время работы функции в некоторых случаях получаются 2 значения а не одно, следовательно я не могу использовать контейнер фиксированного размера для записи туда ответа, возможно ли создать контейнер динамического размера, или использовать стек?

    Данные мне нужно записывать так чтобы их потом можно было использовать в последующем в функции parallel_for_each без создания дополнительных контейнеров.

    23 сентября 2018 г. 15:18

Ответы

  • Ну в таком случае я мог бы просто писать в opengl или directx 

    Так именно так и надо делать на практике. Собственно, все так и делают, 3D движки (для игр например) через эти низкоуровневые API и работают. На сколько я знаю C++ AMP так же через DX работает, так что так или иначе, DX и используется.

    А если вы это для обучения/развлечения делайте, то какая разница как быстро оно работает? Практического применения все равно нет, можно движок писать без всяких AMP. Пусть будет 0.01 fps, для обучения это значения не имеет. Зато не надо отвлекаться на специфику редкого языка и сосредоточиться на алгоритмах.

    Да, конечно же GPU быстро перемножает матрицы 4х4, это основная функция вершинных шейдеров когда они появились.

    Вопрос в том какие именно ресурсы использует C++ AMP на GPU... Вполне возможно что код по факту выполняется на CPU, ведь никому и в голову не могло прийти что кто то будет на C++ AMP треугольники заливать вместо того чтоб использовать функционал GPU для это специально.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    25 сентября 2018 г. 15:36
    Модератор

Все ответы

  • В место динамический массивов обычно рекомендуют использовать списки List<T>.
    23 сентября 2018 г. 16:31
  • можно пожалуйста простой пример использования List в parallel_for_each?
    23 сентября 2018 г. 16:55
  • Типа такого: https://metanit.com/sharp/tutorial/12.4.php
    23 сентября 2018 г. 19:08
  • можете привести пример на c++, я нигде не могу найти информацию, вот к примеру я создаю лист

    list<STURCT_POINT> list1;

    Потом как его параллельно обработать

    parallel_for_each( restrict(amp) {

    });

    Как правильно обьявлять в parallel_for_each()??

    И у меня есть сомнения т.к я хоть и создаю контейнер list он же висит на CPU для использования в GPU надо контейнер array_view или array

    24 сентября 2018 г. 0:08
  • Простите, с плюсами я Вам не помогу. Вот примеры как работать с листами под с++ https://metanit.com/cpp/tutorial/7.6.php надеюсь это чем-то поможет.
    24 сентября 2018 г. 7:28
  • List в C# и std::list в C++, это все же разные вещи (первое - массив переменной длины, второе - связный список). Но в C++ AMP, я полагаю, ни тот ни другой не нужен. Просто выделить памяти с запасом, и сделать первым элементом массива его длину.
    • Изменено VadimTagil 24 сентября 2018 г. 11:59
    24 сентября 2018 г. 11:59
  • очень оригинально... но у меня вообще разное количество значений где-то может быть одно где-то несколько тысяч. И да я согласен что это разные вещи, к тому же List на с++ это контейнер а контейнер контейнера делать по идее нельзя "array_view<int> arr(List list1)" знаю что динамически можно менять vector и он кстате не является контейнером и его можно попробовать обьявить на GPU что то типа

    struct STURCT_POINT{

    int x,y;

    }

    vector <STURCT_POINT> vec1

    array_view<STURCT_POINT > arr(vec1);

    Но у меня ничего не выходит, как-то получалось но в итоге он мне все делал, все выводил, но по завершении выдавал переполнение стека и ошибка.



    24 сентября 2018 г. 13:24
  • Вот здесь есть пример, как создать array_view на основе вектора: https://social.msdn.microsoft.com/Forums/vstudio/en-US/0e69057f-05fb-47f1-b8e9-ca68efe97bbe/passing-an-arrayview-to-a-funciton?forum=parallelcppnative

    Но не факт, что это вам нужно, так как там размер массива все равно в ходе расчета не меняется.

    24 сентября 2018 г. 15:51
  • Хорошо, а как можно организовать тогда чтото вроде стека, в parallel_for_each, пусть я массив возму большой длины? К Примеру у меня есть массив который я буду обрабатывать- 50 элементом ,и за один цикл параллельности получается 2~3 значения ,как мне написать функцию которая будет как бы добавлять в стек, т.е в массив с выделенной памятью 200 элементов
    24 сентября 2018 г. 21:15
  • Но у меня ничего не выходит, как-то получалось но в итоге он мне все делал, все выводил, но по завершении выдавал переполнение стека и ошибка.
    Простите, что вставляю свои пять копеек, хотя не разбираюсь в вопросе... Вы сказали, что у Вас есть решение которое вы построили на использовании vector - динамически расширяемый массив. Раз Ваш алгоритм адекватно выполнял поставленную задачу, то зачем его выбрасывать, может стоит доработать освобождение объектов после расчетов или просто глушить ошибку (вариант на тройку). Возможно ошибка в порядке уничтожения объектов или вычислении индексов доступа к удаляемым объектам. Я прочитала про vector, очень похоже на то что вы искали, хоть в той статье, что я прочитала их тоже называли каким-то контейнером.
    25 сентября 2018 г. 6:23
  • Стек реализуется элементарно, как я уже написал: выделить заранее память под максимально возможное (оцененное заранее) количество элементов и завести переменную под текущую глубину стека. Если у вас размер массива не доходит до сотен мегабайт, это не должно вызывать проблем с выделением памяти (если больше то да, нужно как-то разбивать на части, но я не не знаю, как это эффективно сделать в С++ AMP)
    25 сентября 2018 г. 6:23
  • А с тем вариантом я его выкинул т.к ошибку он мне выводил даже когда у меня 1 элемент,У меня уже скорей возникла новая проблемма, пусть у меня даже будет массив большой длинны то как мне организовать запись в этот массив.
    25 сентября 2018 г. 10:23
  • Проблемма в том что это будет выполняться параллельно и к этой глобальной переменной (глубину) будет обращяться каждый поток и как себя будет вести переменная в этом случае сложно предугадать,нужно делать какуюто синхронизацию т.е при обращении к этой переменной както останавливать потоки, но это по идее очень скажется на производительности.
    25 сентября 2018 г. 10:28
  • Вообщем я пишу для себя 3d движок,и не могу нормально организовать свои данные, т.е есть статический массив со структурой точек треугольника, после умножения на матрицу получается новый треугольник, не во всех случаях(когда треугольник находится между видимой и не видимой областью) и у меня проблемма в том что я не знаю куда его засунуть, естественно через стек было бы проще на много, но я ограничен amp функциями, может не относиться к ветке, но может есть какието другие способы или как это максимально лучше сделать?
    25 сентября 2018 г. 10:38
  • Да, обращения к переменным из разных потоков должны синхронизироваться. Да, это скажется на производительности (вплоть до того, что слишком большая конкуренция потоков за общие ресурсы сделает параллелизм абсолютно бесполезным). 

    Что касается умножения векторов на матрицу, вроде динамический массив тут не нужен. Треугольник задается тремя векторами (как я понимаю), если умножить каждый на матрицу, всегда получится те же 3 вектора, ни больше ни меньше.

    • Помечено в качестве ответа provokator2018 25 сентября 2018 г. 12:40
    • Снята пометка об ответе provokator2018 25 сентября 2018 г. 12:40
    25 сентября 2018 г. 11:12
  • (Там не вектора, а точки, 3 на треугольник)Да я согласен, но дело в том что растеризатор не может  быстро работать с треугольниками большой площади для этого их нужно делить на более мелкие и раскидывать по потокам, но чтобы это сделать я вижу ток 1 нормальный выход это стек, но он по сути не реализуемый для amp, 2ой выход это использование массива в виде некого стека, но это как я уже понял тоже чтото за гранью...
    25 сентября 2018 г. 12:16
  • (Там не вектора, а точки, 3 на треугольник)Да я согласен, но дело в том что растеризатор не может  быстро работать с треугольниками большой площади для этого их нужно делить на более мелкие и раскидывать по потокам, но чтобы это сделать я вижу ток 1 нормальный выход это стек, но он по сути не реализуемый для amp, 2ой выход это использование массива в виде некого стека, но это как я уже понял тоже чтото за гранью...

    Не нужно их раскидывать по "потокам", для этого есть пиксельные шейдеры которые специально для этого и предназначены. А для обработки треугольников давно есть вершинные шейдеры.

    Забавно что C++ AMP как раз их и использует (во всяком случае с этого началось). Это попытка использовать более-менее стандартный язык на специальном железе вроде GPU где потоков как таковых нет. Это на деле неэффективно и имеет сильные ограничения, но на практике иногда (далеко не всегда) компенсируется высоким быстродействием GPU.

    То что вы делайте судя по всему является неудачным изобретением велосипеда где вместо использования графического железа непосредственно для графики вы пытайтесь это сделать через призму универсального языка. Не удивительно что у вас все очень медленно и плохо работает, хотя современные GPU способны закрашивать многие миллиарды пикселей в секунду.

    Кстати, даже если требуется разбивать треугольники на более мелкие (что было необходимо лет 15-20 назад когда GPU имели сильные ограничения в том числе по размеру текстур), то это делалось на уровне модели, а не во время рендеринга.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    25 сентября 2018 г. 13:29
    Модератор
  • Ну в таком случае я мог бы просто писать в opengl или directx ну или еще какие-нибудь интерфейсы, но мне для себя проще "изобрести велосипед" чтобы понять эти процессы в больших деталях(возможно это покажется каким-то садомазахизмом, но будем считать что это хобби...)  на счет вершинного шейдера он не обрабатывает треугольники, он обрабатывает их точки и в итоге получится лишь геометрия, да и на сайте msdn написано как быстро в amp умножать матрицы, и он реально делаает это очень быстро(там банально каждая точка умножается на 4 матрицы(матрыцы-мировая,вида,проекционная,экранная) у всех их размер 4 на 4), но когда мне нужно просто однотонно закрасить по 3ем точкам треугольник(растеризировать) если этот треугольник маленький но их допустим очень много то делается очень быстро ,а если большой треугольник и их очень мало, то глючит, думал дело в рестаризаторе тип много вычислений как оказалось я просто беру описывающий прямоугольник и запоняю его пикселями т.е на поток идет всеголишь 2 цикла без вычислений, и достаточно гдето фигуру 500на 500 пикселей все сразу же начинает глючить по геометрической прогрессии

    25 сентября 2018 г. 14:06
  • Ну в таком случае я мог бы просто писать в opengl или directx 

    Так именно так и надо делать на практике. Собственно, все так и делают, 3D движки (для игр например) через эти низкоуровневые API и работают. На сколько я знаю C++ AMP так же через DX работает, так что так или иначе, DX и используется.

    А если вы это для обучения/развлечения делайте, то какая разница как быстро оно работает? Практического применения все равно нет, можно движок писать без всяких AMP. Пусть будет 0.01 fps, для обучения это значения не имеет. Зато не надо отвлекаться на специфику редкого языка и сосредоточиться на алгоритмах.

    Да, конечно же GPU быстро перемножает матрицы 4х4, это основная функция вершинных шейдеров когда они появились.

    Вопрос в том какие именно ресурсы использует C++ AMP на GPU... Вполне возможно что код по факту выполняется на CPU, ведь никому и в голову не могло прийти что кто то будет на C++ AMP треугольники заливать вместо того чтоб использовать функционал GPU для это специально.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    25 сентября 2018 г. 15:36
    Модератор