C ++ Это форма микро оптимизации

Это микрооптимизация или вообще оптимизация?

void Renderer::SetCamera(FLOAT x, FLOAT y, FLOAT z) {
// Checking for zero before doing addition?
if (x != 0) camX += x;
if (y != 0) camY += y;
if (z != 0) camZ += z;

// Checking if any of the three variables are not zero, and performing the code below.
if (x != 0 | y != 0 | z != 0) {
D3DXMatrixTranslation(&w, camX, camY, camZ);
}
}

Будет ли запуск цикла for .. с условием vector.size () заставлять приложение пересчитывать элементы вектора в каждом цикле?

std::vector<UINT> vect;

INT vectorSize = vect.size();
for (INT Index = 0; Index < vectorSize; Index++) {
// Do vector processing
}

// versus:

std::vector<UINT> vect;

for (INT Index = 0; Index < vect.size(); Index++) {
// Do vector processing
}

Я использую Visual Studio и, что касается второго вопроса, похоже, что-то, что компилятор может оптимизировать, но я просто не уверен в этом.

2

Решение

В зависимости от реализации вектора, компилятор может понимать или не понимать, что размер не изменяется. В конце концов, вы вызываете различные векторные функции внутри цикла, любая из которых может изменить размер.

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

Часто вы хотели бы написать так:

for (size_t i = 0, size = vect.size(); i < size; ++i)
...

Пока мы на этом, похожий подход используется с итераторами:

for (list<int>::iterator i = lst.begin(), end = lst.end(); i != end; ++i)
...

Изменить: я пропустил первую часть:

Это оптимизация?

if (x != 0) camX += x;
if (y != 0) camY += y;
if (z != 0) camZ += z;

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

Во-вторых, и что более важно, они являются плавающими. Это означает, что помимо того факта, что Вы не должны напрямую сравнивать их с 0, в основном они почти никогда не равны 0. Так что ifс 99,9999%.

То же самое относится и к этому:

if (x != 0 | y != 0 | z != 0)

В этом случае, однако, поскольку перевод матрицы может быть дорогостоящим, вы можете сделать:

#define EPS 1e-6 /* epsilon */
if (x > EPS || x < -EPS || y > EPS || y < -EPS || z > EPS || z < -EPS)

и теперь да, по сравнению с матричным умножением, это, вероятно, оптимизация.

Обратите внимание, что я использовал || который замыкается, если, например, с самого начала x > EPS это правда (он не будет рассчитывать остальное), но с | этого не произойдет.

5

Другие решения

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

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

Для вашего второго случая, size должно быть постоянным временем и почти наверняка будет указывать на прямой доступ к vectorразмер. Скорее всего, полностью оптимизируемый. Тем не менее, иногда это может сделать код / ​​цикл более легким для чтения, сохраняя размер, потому что это ясно показывает, что вы утверждаете, что размер не изменится во время цикла.

2

Во-первых, что касается vector.size(), увидеть
этот ТАК вопрос. С другой стороны, я не видел реализации, где std::vector::size() не O (1).

if (x != 0) camX += x; этот cmp и как следствие jne однако будет медленнее, чем просто добавление переменной x не важно что. Изменить: Если вы не ожидаете более 50% пропусков кэша на camX

2

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

void Renderer::SetCamera(FLOAT x, FLOAT y, FLOAT z) {

if (x != 0 || y != 0 || z != 0) {
camX += x;
camY += y;
camZ += z;
D3DXMatrixTranslation(&w, camX, camY, camZ);
}
}

если все x, y а также z равны нулю, ничего не нужно делать, иначе делать все.

Во-вторых, компилятор может поднять vector.size() вне цикла, если он может определить, что размер не изменяется во время выполнения цикла. Если компилятор не может определить это, он не должен поднимать size() вычисления вне цикла.

Делать это самостоятельно, когда вы знаете, что размер не меняется, — это хорошая практика.

1
По вопросам рекламы [email protected]