Сохранение конвейера выполнения - PullRequest
1 голос
/ 02 декабря 2009

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

if(!ret)
{
   doNoErrorCode();
}
exit(1);

или

if(ret)
{
   exit(1);
}
doNoErrorCode();

С одной стороны, тяжеловесные процессоры могут спекулировать о ветвях, взятых в непосредственной близости / местности, используя простую статистику - я изучил 4-битный механизм для спекуляций ветвей (-2, -1,0, + 1, + 2), где ноль неизвестно и 2 будет считаться истинной веткой.

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

  1. Когда код не является часто посещаемым циклом, для которого булево значение смещено при заполнении конвейера?
  2. Предположение о ветвлении должно начинаться либо с true, либо с false, либо с нуля (конвейер должен быть чем-то заполнен). Что это может быть?

Ответы [ 2 ]

2 голосов
/ 03 декабря 2009

В gcc вы можете использовать <a href="http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html" rel="nofollow noreferrer">__builtin_expect</a>, чтобы предоставить компилятору информацию о предсказании перехода. Чтобы сделать это немного проще, вы можете заимствовать вероятные / маловероятные используемые макросы, например в ядре Linux:

#define likely(x)       __builtin_expect((x),1)
#define unlikely(x)     __builtin_expect((x),0)

, а затем, например,

if (unlikely(!some_function())
    error_handling();
2 голосов
/ 02 декабря 2009

Поведение зависит от процессора, и компилятор часто переупорядочивает инструкции. В этих руководствах вы найдете всю необходимую информацию: http://agner.org/optimize/.

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

...