Трэвис Даунс в недавнем посте рассказал, что некоторые компиляторы C++ испытывают проблемы в производительности при заполнении массивов нулями. Даниэль Лемир продолжил разговор об этой проблеме в своём блоге и провёл наглядный тест для двух подходов.
Как правило, чтобы заполнить массив некоторым значением, C++ программисты вызывают std::fill
. Можно предположить, что для такой простой задачи, как заполнение массива нулями, стандартная библиотека C++ обеспечивает наилучшую производительность. Однако в случае компиляторов GNU GCC это не так.
Следующая строка кода на C ++ компилируется как цикл, который заполняет каждый отдельный байт нулями с применением обычного флага оптимизации -O2
.
Когда массив большой, этот подход становится менее эффективен, чем реализации функций C, например, memset
.
Трэвис объясняет, как исправить код С++, чтобы он работал так же быстро, как функция memset
.
Что насчёт очень больших массивов? Что делать, если нужно записать нули во всём двухгигабайтном массиве? Результаты теста на 2 Гб массиве следующие:
memset |
30 Гб/c |
std:fill |
1.7 Гб/c |
Функция memset
в проведённом тесте в 15 раз быстрее, чем std::fill
. Это показывает, что при работе с большими объёмами данных, вас может ограничивать не пропускная способность, а просто неэффективная реализация алгоритма. Заполнение через std::fill
в этом случае работает медленнее, чем хороший сетевой адаптер или быстрый диск.
Другой урок, который можно извлечь из этого примера, состоит в том, что просто писать код на C++ недостаточно для обеспечения хорошей производительности. Хотя существует много технических решений, направленных на то, чтобы сделать C++ быстрым, и, обычно всё прекрасно работает, нужно сохранять бдительность.
Ссылка на более подробные результаты теста.
Публикации Библиотеки программиста по языку C++ доступны по тегу.
Комментарии