Manifold Geometry // Многообразная Геометрия

Злобно про параллельные вычисления

/ Просмотров: 1402

Как-то давно уже чесались руки пройтись по теме параллельных вычислений, и вот возник очередной (за несколько дней подряд) повод. Почему-то народ упорно считает, что геометрические ядра де «устарели», ибо архитектура параллельных вычислений не была-мол заложена в них изначально. Соответственно развивается дискурс создания геометрического ядра «нового поколения», по-красноармейски красиво и размашисто решающего проблему путем внедрения очередного TBB/OpenMP или даже OpenCL. Вроде бы, да, отчего не использовать параллелизм, когда на дворе, понимаешь ли, двадцать первый век, аппаратура вон как эволюционировала, а САПР по-прежнему плетется методологически где-то в застойных восьмидесятых и знать не желает никакого параллелизма.

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

  1. Как так вышло, что, например, Parasolid-овские булевы операции работают от 100 до 1000 раз быстрее тех же каскадовских (информация от источника, вызывающего доверие) в однопоточном режиме?
  2. Не является ли попытка распараллелить медленные вычисления лобовой атакой на проблему, существенно более глубокую и сложную? Аналогия: для вспашки поля вы привлекаете 10 человек с лопатой, хотя один трактор справится существенно лучше.
  3. Всегда ли допустимо, что в многозадачной среде одно приложение начинает перетягивать одеяло CPU на себя, занимая все ядра процессора и не оставляя пользователю возможности заняться чем-то еще, пока идет фоновый процесс?

Почти всегда, когда кто-то начинает внедрять куда-то параллельные вычисления, речь идет о неуклюжей попытке сорвать низковисящий фрукт. Приведу пример. В проекте возникла ситуация: булева операция работает медленно. Смотришь на нее через призму профилировщика и наблюдаешь 90% времени, ушедшие на пересечение и объединение тел. Возникает интуитивное желание включить параллельный режим обработки данных, который, действительно, дает существенный прирост производительности, и вся операция вместо 20 секунд занимает, например, 8. Казалось бы, вот она — победа. Но при внимательном изучении оказалось, что сама модель, на которой тормозят вычисления, представлена чрезмерно сложным сплайном, содержащим десятки тысяч контрольных точек на сравнительно простой линейчатой форме. Понизив сложность модели, мы получем доли секунды в однопоточном режиме и не пытаемся параллелить БЕССМЫСЛЕННЫЕ вычисления.

Золотое правило: наиболее эффективным является вычисление, которого не было. Вычислений надо избегать, а не пытаться молотить их со всех орудий одновременно, «в труху». Сначала добиваемся быстрой работы в одном потоке, а затем смотрим, не осталось ли возможности нагрузить другие ядра полезной работой. Анонимус поспорит, очевидно, что автор этих строк не понимает элементарного, ведь алгоритмы должны изначально допускать параллелизм. Требуется, мол, изменить свое однопоточное мышление и научиться думать в несколько ядер одновременно. Так, мол, и достигается истинно параллельная архитектура. Все так, спорить не с чем. Однако есть нюанс: как часто внедрение параллелизма идет именно таким путем, от задачи? Не выходит ли на практике, что мы пытаемся проделать в ведре много маленьких дырок для слива воды, вместо того, чтобы просто его перевернуть?