Подтвердить что ты не робот

Как не оптимизировать - механики безумной функции

Я искал технику программирования, которая обеспечивала бы, чтобы переменные, используемые для бенчмаркинга (без наблюдаемых побочных эффектов), не были оптимизированы компилятором

Это дает некоторую информацию, но в итоге я использовал folly и следующая функция

/**
 * Call doNotOptimizeAway(var) against variables that you use for
 * benchmarking but otherwise are useless. The compiler tends to do a
 * good job at eliminating unused variables, and this function fools
 * it into thinking var is in fact needed.
 */
#ifdef _MSC_VER

#pragma optimize("", off)

template <class T>
void doNotOptimizeAway(T&& datum) {
  datum = datum;
}

#pragma optimize("", on)

#else
template <class T>
void doNotOptimizeAway(T&& datum) {
  asm volatile("" : "+r" (datum));
}
#endif

Я хочу использовать выше, но у меня малое понимание его работы. Меня больше всего интересует часть, отличная от VС++, и почему/как строка

asm volatile("" : "+r" (datum));

создает не оптимизируемый контекст или , почему это то, что можно было бы выбрать для реализации такой вещи. Также было бы интересно сравнить два метода (я не знаю, как работает pragma optimize, но выглядит как более чистое решение - не переносимо)

4b9b3361

Ответ 1

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

В любом случае, в GCC,

asm volatile("" : "+r" (datum));

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

Часть после : сообщает GCC о влиянии кода сборки. "+r" (datum) означает, что GCC должен предположить, что код сборки считывает и изменяет datum. Хотя это не так. Причина этого в том, что любые более ранние вычисления, которые в конечном итоге сохраняют значение в datum, не могут быть отброшены как ненужные. В то же время сам код сборки не может быть отброшен как ненужный из-за потенциальной модификации datum. volatile также отмечает код сборки как код, который нельзя оптимизировать, как описано здесь:

Оптимизаторы GCC иногда отбрасывают операторы asm, если они определяют отсутствие выходных переменных. Кроме того, оптимизаторы могут перемещать код из циклов, если они считают, что код всегда будет возвращать тот же результат (т.е. Ни одно из его входных значений не меняется между вызовами). Использование квалификатора volatile отключает эти оптимизации. [...]

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

Ограничение r означает, что код не заботится обо всем, что регистрирует GCC для использования кода сборки, и здесь документируется:


Регистр-операнд допускается при условии, что он находится в общем регистре.

Модификатор + означает, что код может читать и записывать в datum, а здесь описано:

"+
Означает, что этот операнд читается и записывается инструкцией. [...]