2013-03-02 4 views
-2

Давайте предположим, что мы имеем эту структурубыстрые «для» петель

struct structure 
{ 
    type element; 
    int size; 
} 

и мы в основном и мы хотим перебрать что-то.

Это быстрее

for (int i = 0; i < structure.size; ++i) 

или

int size = structure.size; 
for (int i = 0; i < size; ++i) 

?

Имеет ли вес более непрерывное связывание с sctructure в первом методе или дополнительном пространстве памяти, а также время, затрачиваемое на создание первой переменной в первой строке метода n.2?

Я не вижу другого различия между ними, поэтому, если вы это сделаете, пожалуйста, поделитесь!

EDIT: Я отредактировал этот вопрос так, чтобы он стал кратким, простым и легким. Пожалуйста, пересмотреть голосование, которое вы ему дадите. Спасибо.

+0

Вы измерили его? –

+8

Идеальная тема для этой цитаты: «Программисты тратят огромное количество времени на размышления о скорости некритических частей своих программ или беспокоятся о скорости их некритических частей, и эти попытки эффективности действительно оказывают сильное негативное влияние при рассмотрении отладки и обслуживания. забудьте о небольшой эффективности, скажем, около 97% времени: преждевременная оптимизация - это корень всего зла, но мы не должны упускать наши возможности в этих критических 3% » – mariozski

+0

Оба равны. Я уверен, что ваш компилятор достаточно умен, чтобы оптимизировать код уровень. с GCC вы можете явно форсировать для лучшей оптимизации с флагом '-o3, -o2' –

ответ

3

Там может быть хорошая причина, чтобы выбрать один над другим. Если содержимое вашего цикла в первом примере изменит значение structure.size, то i будет постоянно проверяться на текущее значение. Однако в вашем втором выборе size не изменится, так как structure.size делает. Какой из них вы хотите, зависит от проблемы. Я бы, возможно, изменил вместо этого size вместо initialSize.

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

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

0

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

Хотя в случае цикла вы вызываете функцию, которая может изменять эту структуру, а компилятор не имеет доступа к ее реализации, второй вариант может помочь, поскольку вы даете компилятору намек на то, что ему не нужно перезагружать struct.size из памяти. Я бы рекомендовал использовать сопзЬ:

const int size = structure.size; 
for (int i = 0; i < size; ++i) { 
    somefunc(&structure); 
} 
+0

, если вы так скажете, что мой компилятор сделает для оптимизации моего кода? приблизится ли он к первой или ко второй версии? – doplumi

+0

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

0

Очень маловероятно, что будет какая-либо фактическая разница в скомпилированном коде из этого, если это не действительно древний компилятор с действительно мусорными оптимизациями. Все, что было похоже на gcc, clang, MSVC или компиляторы Intel C++, создало бы точно такой же код для этих сценариев.

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

std::string str; 

cin >> str; 
for(int i = 0; i < str.size(); i++) 
{ 
    if (str[i] > 'a') 
     str+= 'B'; 
} 

тогда у нас другая история ...

0

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

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

-1

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

В вашем втором методе, поскольку размер является локальной переменной текущего блока кода, он будет правильно сохранен в кеше.

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

См. Load-Hit-Store для более полного объяснения.