Является ли алгоритмический анализ путем подсчета флопов устаревшим?

43

На моих курсах по численному анализу я научился анализировать эффективность алгоритмов, подсчитывая количество операций с плавающей запятой (флоп), которые им требуются, в зависимости от размера проблемы. Например, в тексте Trefethen & Bau о числовой линейной алгебре есть даже трехмерные изображения подсчетов флопа.

Сейчас модно говорить, что «флопы свободны», потому что задержка памяти для извлечения чего-либо, не находящегося в кеше, намного превышает стоимость флопа. Но мы все еще учим студентов считать флопы, по крайней мере, на курсах численного анализа. Должны ли мы учить их считать доступ к памяти? Нужно ли нам писать новые учебники? Или доступ к памяти слишком специфичен для конкретной машины, чтобы тратить на нее время? Какова будет долгосрочная тенденция с точки зрения того, являются ли провалы или доступ к памяти узким местом?

Примечание: некоторые из приведенных ниже ответов, похоже, отвечают на другой вопрос, такой как «Должен ли я одержимо переписать свою реализацию, чтобы сохранить несколько провалов или улучшить производительность кэша?» Но то, что я спрашиваю, больше похоже на « Полезно ли оценивать алгоритмическую сложность с точки зрения арифметических операций или обращений к памяти

Дэвид Кетчесон
источник
1
> «Полезнее ли оценивать алгоритмическую сложность с точки зрения арифметических операций или обращений к памяти?» , С практической точки зрения встроенные системы по-прежнему ограничены скоростью FPU, а не пропускной способностью памяти. Таким образом, даже если подсчет провалов считается стандартом HPC устаревшим, он все еще имеет практическое применение для других сообществ.
Дэмиен

Ответы:

31

Я думаю, что (первый порядок) правильно сделать, это посмотреть на соотношение флопов и байтов, необходимое в алгоритме, который я называю . Пусть - максимальная частота флопа процессора, а - максимальная полоса пропускания. Если , то алгоритм будет ограничен по пропускной способности. Если , алгоритм ограничен на флопе.βFmaxBmaxFmaxβ>BmaxBmaxβ>Fmax

Я думаю, что подсчет обращений к памяти является обязательным, но мы также должны подумать о:

  • Сколько локальной памяти требуется

  • Сколько возможного параллелизма у нас

Затем вы можете начать анализировать алгоритмы для современного оборудования.

Мэтт Кнепли
источник
3
Я согласен с Мэттом, но хочу отметить, что настоящее время достаточно часто встречается в литературе как "арифметическая интенсивность" и "численная интенсивность". Я думаю, что модель Roofline Уильямса, Уотермана и Паттерсона , вероятно, является хорошим началом для размышлений об этих проблемах. Я думаю, что это должно быть расширено до соотношения памяти / флопа алгоритма во времени. β
Арон Ахмадиа
2
Дэвид делает больше 8 лет назад.
Мэтт Кнепли
3
Итак, есть лучшая, более сложная модель (как всегда). Но эта модель дает ответ, который зависит от машины. Что мы должны научить студентов использовать в качестве первого анализа?
Дэвид Кетчон
3
Дело в том, что машина была сведена к одному числу, отношение пиковых провалов к пиковой пропускной способности, как и алгоритм. Это так просто, как только может. Без вычислительной модели любая оценка сложности бесполезна, и это самая простая реалистичная оценка.
Мэтт Кнепли
1
Я думаю, вы неправильно поняли проблему. У нас уже есть оптический транспорт, который может перевозить большие грузы. Проблема заключается в том, чтобы получить это на чипе. У вас только так много проводов и максимальная тактовая частота. Оптический транспорт только уменьшит эту проблему на оптическом чипе.
Мэтт Кнепли
22

Я не понимаю, почему нужно быть «победителем»; это не игра с нулевой суммой, где количество флопов и доступ к памяти должны заглушить другого. Вы можете научить их обоих, и я думаю, что они оба используют. В конце концов, трудно сказать, что ваш алгоритм с обращениями к памяти обязательно будет быстрее, чем ваш алгоритм с доступами. Все зависит от относительной стоимости различных частей (этот надоедливый фактор, который мы всегда игнорируем в этих анализах!).O ( N )O(N4)O(N)O(NlogN)O(N2)

В более широком плане, я думаю, что анализ алгоритмической производительности должен быть «всеобъемлющим». Если мы учим людей быть настоящими разработчиками и пользователями высокопроизводительных вычислений, им необходимо понять, какова стоимость программирования в реальном мире. Модели абстрактного анализа, которые мы имеем, не учитывают время программиста. Мы должны думать с точки зрения «общего времени до решения», а не просто подсчета флопов и алгоритмической эффективности. Нет смысла тратить три или четыре дня программиста на переписывание подпрограммы, которая сэкономит одну секунду компьютерного времени на задание, если вы не планируете выполнить несколько миллионов вычислений. Точно так же инвестиции в несколько дней, чтобы сэкономить час или два вычислительного времени, быстро окупаются. Этот новый алгоритм может быть удивительным,

aeismail
источник
7
, алгоритм , который выполняет доступ к данным? :)O(NlogN)O(N2)
Андреас Клекнер
2
Почему бы нет? Если относится только к операциям с плавающей запятой, возможно, существует дополнительное значительное число операций с целочисленными значениями, которые вызывают доступ к данным :)O(NlogN)O(N2)
kini
9

Как уже отмечали другие, ответ, конечно, зависит от того, является ли узкое место ЦП или пропускная способность памяти. Для многих алгоритмов, которые работают с некоторым набором данных произвольного размера, узким местом обычно является пропускная способность памяти, поскольку набор данных не помещается в кэш ЦП.

Более того, Кнут упоминает, что анализ доступа к памяти с большей вероятностью выдержит испытание временем, предположительно потому, что он относительно прост (даже с учетом удобства кэширования) по сравнению со сложностями современных конвейеров ЦП и прогнозированием ветвлений.

Кнут использует термин gigamems в томе 4A TAOCP при анализе BDD. Я не уверен, использует ли он это в предыдущих томах. Он сделал вышеупомянутый комментарий о том, как выдержать испытание временем в своей ежегодной рождественской лекции в 2010 году.

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

Джейсон Дэвис
источник
8

То, как вы определяете стоимость алгоритма, зависит от того, на каком «уровне» научных вычислений вы работаете, и какой (узкий или широкий) класс проблем вы рассматриваете.

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

С другой стороны, чем шире класс задач, тем меньше вы можете предсказать фактические вычисления (например, вы не знаете, насколько разреженными будут входные матрицы вашей реализации CG). Чем шире класс машин, на которых должна работать ваша программа, тем меньше вы можете предсказать архитектуру Cache.

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

В conclusio оптимизация кэша полезна только в том случае, если нечего оптимизировать за счет параллелизма и уменьшения асимптотического числа FLOP.

Я думаю, что разумно адаптировать позицию теоретической информатики: в конце концов, улучшение асимптотической сложности алгоритма дает большую отдачу, чем микрооптимизация некоторых существующих строк кода. Поэтому подсчет FLOPs все еще предпочтителен.

shuhalo
источник
«Оптимизация кэша полезна только в том случае, если нечего оптимизировать за счет параллелизма и уменьшения асимптотического числа FLOP». Я не согласен. Если вы хотите вычислить большое выражение большого набора чисел, лучше выполнять один шаг за раз со всеми числами, чем все шаги для каждого числа. Оба имеют одинаковое количество FLOPS, но один лучше в доступе к памяти. Бонус, если вы выбираете размер сгустка для размещения в кеше (или компилятор сделает это за вас). Это то, что Numberxpr делает в Python: github.com/pydata/numexpr
Davidmh
6

Я всегда отказывался даже думать о подсчете флопов, обращений к памяти или о том, что у вас есть. Это концепция 1960-х годов, когда то, что вы делали, было в значительной степени дано, и только то, как вы это делали, зависело от алгоритмической оптимизации. Подумайте о решении проблемы конечных элементов на равномерной сетке XYZ, используя либо гауссовское исключение итерации Якоби.

Теперь вы можете оптимизировать это до чертиков и сэкономить несколько флопов, получая 10% времени выполнения. Или вы можете подумать о реализации многосеточного метода и оптимальной предварительной обработки блоков с коэффициентом 10 во время выполнения. Это то, чему мы должны обучать наших учеников - подумать о том, какие сложные внешние алгоритмы могут помочь вам при поиске лучшего внутреннего алгоритма. У вашего босса (Киз) есть эти слайды о прогрессе в вычислениях MHD, которые делают эту точку зрения довольно очевидной.

Вольфганг Бангерт
источник
На самом деле я спрашивал о том типе мышления, который вы предлагаете, а не о низкоуровневой оптимизации. Какой показатель следует использовать, чтобы определить, будет ли multigrid и ваш прекондиционер быстрее альтернатив?
Дэвид Кетчон
Я не знал бы, как подсчитать вручную - FLOPS или любые другие команды для сложных алгоритмов, которые работают с десятками или тысячами строк кода. Подумайте, например, насколько сложна фаза анализа и построения алгоритмов AMG. В этих алгоритмах так много частей, и все они зависят от реальных данных, поэтому вы не можете предсказать количество операций.
Вольфганг Бангерт
1
Я думаю, что сначала я неправильно понял, к чему вы пришли, но я все еще не согласен с вашей точкой зрения. «Внешние алгоритмы» могут (и я бы сказал, должен) разрабатываться с учетом асимптотической сложности. Конечно, вы не станете утверждать, что переход от квадратичного алгоритма к почти линейному алгоритму в лучшем случае приведет к сокращению времени выполнения на 10%; тем не менее, как еще количественно оценить асимптотическую сложность, чем с помощью флопов и / или операций памяти?
Джек Полсон
7
Я думаю, что этот подход "подбросить руки" к алгоритмам - дерьмо. Вам нужно упростить анализ, рассматривая только затраты первого порядка и упрощая модель, чтобы ее можно было отслеживать, но говорить, что вы не можете анализировать что-то вроде MG или Cholesky, потому что это слишком сложно, категорически неправильно.
Мэтт Кнепли
1
Хорошо, но что значит анализировать MG или Cholesky, когда каждый FLOP, который вы считаете, скрыт за несколькими уровнями задержки, вызванной гиперпоточными процессорами, кэшами, медленной оперативной памятью, мультискалярными процессорами и автоматической векторизацией? Я подчеркиваю, что в пределах 5-10 раз вы не можете прогнозировать время выполнения ваших алгоритмов, не рассчитывая его время. Это было совершенно другое в 50-х и 60-х годах, когда люди начали подсчет FLOP.
Вольфганг Бангерт
1

Да, устарел. Алгоритмический анализ с помощью флопов или любого другого метода полезен только в качестве абстрактной модели машины при рассмотрении масштаба рассматриваемой проблемы. Фактическая производительность зависит как от реализации, так и от аппаратного обеспечения, и применимость любой абстрактной модели для последней к реальности со временем уменьшается. Например, когда вы продолжаете распараллеливать реализацию сложного алгоритма, такого как молекулярная динамика, разные аспекты становятся ограничивающими скорость на разных аппаратных средствах, а алгоритмический анализ не имеет ничего общего с наблюдениями. В одном смысле единственной важной вещью является измерение производительности реализации алгоритма (ов) для рассматриваемого аппаратного типа (типов).

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

mabraham
источник
-1

На самом деле не отвечаю на ваш вопрос, но добавлю еще одну переменную, которую нужно учесть: особенности языка программирования. Например, Python sortиспользует алгоритм Timsort , который разработан (среди других приятных свойств), чтобы минимизировать количество сравнений, которые могут быть потенциально медленными для объектов Python. С другой стороны, сравнивать два числа с плавающей точкой в ​​C ++ очень быстро, но их замена обходится дороже, поэтому они используют другие алгоритмы.

Другими примерами являются динамическое распределение памяти (тривиально в списке Python, быстрое как во время выполнения, так и во время разработки, просто .append()), против FORTRAN или C, где, хотя это возможно и быстрее при правильной реализации, это требует значительно больше времени на программирование и мозг. Смотрите Python быстрее, чем Фортран.

Davidmh
источник
Это правда, но, как вы говорите, не отвечает на вопрос. Это на другую тему.
Дэвид Кетчесон
Что ж, при правильном анализе это то, что нужно учитывать при принятии решения, какой алгоритм реализовать.
Davidmh