воскресенье, 22 декабря 2019 г.

Межъязыковые тесты производительности



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

Если производительность оценивается на основе одного-двух тестов, тем более без перекомпиляции, то к производительности этот тест никакого отношения не имеет. Тут можно было бы упомянуть, например, тесты 7zip, которые таки интересные, но надо понимать что измеряют они только скорость конкретного алгоритма.

Но вернёмся к Benchmark Game. Мне очень понравился подход автора, который заключается в следующем: берём какой-то алгоритм, пишем его решение на соответствующем языке, сравниваем время работы получившейся программы с реализациями алгоритма на других яхыках. Однако в данном проекте есть проблемы, которые не позволяют сделать реальную оценку производительности ни языков, ни компиляторов, ни процессоров.

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

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

В-третьих в тестах нет разделения на однопоточный/монгопоточный режим. Это ещё больше сужает наше видение относительной скорости системы.

Кажется были ещё какие-то идеи касательно этого проекта, но сейчас я уже немножко про них подзабыл. Я смог найти несколько схожих проектов (хотя их довольно мало). Во-первых это старый проект, из которого вырос benchmark game: Great Language Shootout. Это был проектик, изначально замерявший скорость скриптовых языков. Что довольно интересно, хотя и имеет не так много смысла (жаль что в актуальном проекте их нет just for fun).

Ещё из крупных пузомерок можно назвать проект Web Framework Benchmarks с довольно говорящим названием. Но в нём измеряется преимущественно скорость веб-фреймворков, уж не знаю на сколько качественно - я в них совершенно не разбираюсь.

Есть ещё один интересный любительский проектик от некоего Кости. В нём неплохая подборка языков, но он нацелен не на поиск самого быстрого языка, а на сравнительный анализ программ, написанных "средним разработчиком" (полагаю автор имел ввиду себя). Тестовых задания в проекте немного, но много реализаций на разных языках. Особенно понравилось сравнение скорости реализации языка Brainfuck. У автора явно имеется неплохое чувство юмора.

Если у кого-либо есть ещё ссылки на аналогичные интересные проекты - буду рад услышать.

А теперь подумаю над тем как бы я видел проект по измерению скорости работы различных языков.

1. В таком проекте должно быть множество тестов, направленных на измерение различных аспектов современных программ. Должны быть тесты на различные типы вычислений, на работу с памятью, на работу с большим количеством вызовов и т.п. Т.е. покрыто максимально большое количество областей применений языка программирования. Причём очень желательно чтобы со временем тесты пополнялись актуальными для данного времени задачами.

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

3. Время работы теста должно быть достаточно большим - для замеров важно чтобы выбросы +/- 2 секунды не влияли на итоговый результат. Вообще, каждый тест следует запускать по нескольку раз и брать минимальное значение (мы же ведь наилучший случай ищем).

4. Измерение времени должно быть точным: нужно предоставлять sys,user,real время для каждого запуска. Заодно позволит проверить корректность замера.

5. Программы должны быть корректными: тестовые данные должны быть разнообразными, программа должна уметь с ними работать. В идеале каждая программа должна быть оттестирована различными способами, не только на заранее известных входных данных. Более того, каждая программа должна соответствовать стандарту (привет -Wall -Werror для C/C++).

6. Программы следует измерять в различных режимах. Во-первых, как я уже упоминал, следует отдельно держать тесты для однопоточной и многопоточной реализации. Кроме того, следует иметь отдельные измерения для базового (т.е. без компиляторных оптимизаций) и пикового (т.е. со специально подобранными опциями) режимов.

7. В результатах следует указывать характеристики машины, на которой всё запускалось. Т.е. нужно знать архитектуру, микроархитектуру, свойства памяти, версию ядра, версию компилятора, вообще всё что может хоть как-то влиять на результаты.

8. Для каждого процессора более оптимальной может быть своя версия реализации алгоритма. Более того, существует практика подбора специальных библиотек для накрутки результата (привет, jmalloc, которым на спеках результат накручивают). Для тестов SPEC мне это кажется не особо честным, но в случае соревонавания по получению наиболее быстрой программы сойдёт.

9. Сложность реализации каждого теста. Это очень большой вопрос, т.к. простые тесты не дают понимания реальной производительности, а сложные тесты на разных языках никто не будет поддерживать. Так что я понимаю почему в benchmark game был выбран именно такой подход.

Это всё мысли, которые приходят при беглом анализе существующих бенчмарков. Даже из них можно видеть что это очень сложная задача, которая не поднимается одиночками, а хорошие наборы стоят тысячи долларов. В то же время, эти (и многое другие вещи) стоит помнить когда кто-то пытается рассуждать о том что язык X быстрее языка Y.

Обновление:

В обсуждения принесло ссылку на весьма занятный проект "Розетского камня" для языков программирования. Хотя там не делается замеров, но объясняется как на каждом языке программирования реализовать ту или иную конструкцию. В общем, мне понравилось.

Комментариев нет:

Отправить комментарий