очистив небольшую целочисленный массив: остановлюсь и на петли


существует два способа обнуления массива integer / float:

memset(array, 0, sizeof(int)*arraysize);

или:

for (int i=0; i <arraysize; ++i)
    array[i]=0;

очевидно, что memset быстрее для больших arraysize. Однако в какой момент накладные расходы memset на самом деле больше, чем накладные расходы цикла for? Например, для массива размером 5 - что будет лучше? Первый, второй, а может быть, даже не прокатанная версия:

array[0] = 0;
array[1] = 0;
array[2] = 0;
array[3] = 0;
array[4] = 0;
4 55

4 ответа:

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

например, вот некоторые примечания к выпуску из GCC 4.3:

генерация кода перемещения блока (memcpy) и блок установить (memset) был переписан. GCC теперь может выбрать лучший алгоритм (цикл, развернутый цикл, инструкция с префиксом rep или a вызов библиотеки) на основе размера блок копируется и процессор оптимизировано для. Новая опция -minline-stringops-dynamically есть были добавлены. С помощью этой опции строка операции неизвестного размера расширено таким образом, что небольшие блоки скопировано встроенным кодом, в то время как для большие блоки используется вызов библиотеки. Это приводит к более быстрому коду, чем -minline-all-stringops когда реализация библиотеки способна использование подсказок иерархии кэша. Этот эвристический выбор особый алгоритм может быть перезаписан через -mstringop-strategy. Недавно также memset из значений, отличных от 0 является встроенный.

возможно, компилятор сделает что-то подобное с альтернативными примерами, которые вы дали, но я бы поспорил, что это менее вероятно.

и grep-способный и более сразу очевидный с первого взгляда, что намерение состоит в загрузке (не то, что цикл особенно трудно Грок либо).

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

char arr[5];
memset(arr, 0, sizeof arr);

на

movl  x0, <arr+0x0>
movb  x0, <arr+0x4>

это не становится лучше, чем это...

нет способа ответить на вопрос без оценки. Это будет полностью зависеть от реализации компилятора, процессора и библиотеки времени выполнения.

memset () может быть битом "запаха кода", потому что он может быть подвержен переполнению буфера, изменению параметров и имеет неудачную способность только очищать "байт-мудрый". Однако это безопасная ставка, что она будет "самой быстрой" во всех, кроме крайних случаев.

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

#define CLEAR(s) memset(&(s), 0, sizeof(s))

это обходит вычисления размера и устраняет проблему замены параметров length и vlaue.

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

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

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

надеюсь, что это может помочь кому-то