Разница в скорости между глобальной и объектной переменной - PullRequest
0 голосов
/ 23 сентября 2010

Доступ к глобальной или объектной переменной быстрее?

В C ++ я имею в виду разницу между

::foo

и

this->foo

В ассемблере x86 это в основном означает

mov eax, offset foo

против

mov eax, dword ptr[edx+foo]

Ожидается, что все данные в обоих случаях будут в кеше.

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

Ответы [ 5 ]

8 голосов
/ 23 сентября 2010

Вам нужно проверить и время оба.

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

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

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

4 голосов
/ 23 сентября 2010

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

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

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

3 голосов
/ 23 сентября 2010

Как всегда, следуйте тому, что делает код проще.

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

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

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

Но если код стоит оптимизировать, то его также стоит измерить.

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

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

3 голосов
/ 23 сентября 2010

Рассматривали ли вы третий вариант?

void bar()
{
   foo_t myFoo = ::foo; // or this->foo
   for(;;)
   {
       // do something with myFoo
   }
   ::foo = myFoo;
}

В этом случае компилятор, скорее всего, поместит foo в регистр, который наверняка будет даже быстрее, чем доступ к кешу.

1 голос
/ 23 сентября 2010

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

Возможно, вы захотите использовать размещение нового , чтобы гарантировать, что объект, содержащий foo, находится в удобном месте в памяти, чтобы избежать ошибок страницы.1005 *

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