Прогнозирование ветвей и UB (неопределенное поведение) ⇐ C++
Прогнозирование ветвей и UB (неопределенное поведение)
Я кое-что знаю о предсказании ветвей. Это происходит на процессоре и не имеет ничего общего с компиляцией. Хотя вы можете сообщить компилятору, является ли одна ветвь более вероятной, чем другая, например. в C++20 через [[вероятно]] и [[маловероятно]] (см. cppreference) это отдельно от прогнозирования ветвления, которое выполняет ЦП (см. «Могу ли я улучшить предсказание ветвления с помощью моего кода?).
Насколько я знаю, когда у меня есть, например. Цикл (с условием выхода) ЦП прогнозирует, что условие выхода не будет выполнено, и пытается выполнить некоторые операции внутри цикла, даже если условие еще не проверено. Если ЦП прогнозирует правильно, это экономит некоторое время, и все в порядке. Однако что произойдет, если он не сможет предсказать это правильно? Я знаю, что это приведет к снижению производительности, но я не знаю, будут ли некоторые уже выполненные операции отменены или отменены, или как они с этим справятся.
Теперь я придумал два простых примера. Первый из них (если игнорировать тот факт, что компилятор может просто вычислить сумму во время компиляции, и я предполагаю, что никакой оптимизации не происходит) должен быть очень легко предсказать для ЦП. Условие цикла будет одинаковым все время, а условие в цикле переключается только один раз. Это означает, что прогноз даст нам хороший прирост производительности, и даже если он несколько раз потерпит неудачу, добавление числа можно легко отменить.
Во втором примере условие выхода снова легко предсказать. В теле цикла я выделяю новый массив int с помощью malloc. Обратите внимание, что я не освобождаю его намеренно, так как хочу, чтобы выделение выполнялось успешно в течение длительного времени, чтобы ЦП предсказывал этот успех. В какой-то момент выделение не удастся, если у меня закончится память (я не рассчитал общее потребление памяти и предположу, что память не будет перемещена на диск) или произойдет какая-то другая ошибка. Это означает, что ptr будет иметь значение NULL и его разыменование будет UB. Неизвестно, что произойдет, это может быть просто сбой, привести к сбою моей программы или к тому, что мой компьютер улетит. Поэтому я делаю вывод, что процессор не может просто отменить это, и мне интересно, что произойдет.
#include #define ВЕРСИЯ 1 #if ВЕРСИЯ == 1 интервал основной() { size_t сумма = 0ull; for (size_t i = 0ull, max = 1'000ull; i < max; ++i) { если (я < (макс/2)) { сумма += 2 * я; } еще { сумма += я; } } вернуть 0; } #еще интервал основной() { INT* ПТР = NULL; for (size_t i = 0ull, max = 1’000’000ull; i
Я кое-что знаю о предсказании ветвей. Это происходит на процессоре и не имеет ничего общего с компиляцией. Хотя вы можете сообщить компилятору, является ли одна ветвь более вероятной, чем другая, например. в C++20 через [[вероятно]] и [[маловероятно]] (см. cppreference) это отдельно от прогнозирования ветвления, которое выполняет ЦП (см. «Могу ли я улучшить предсказание ветвления с помощью моего кода?).
Насколько я знаю, когда у меня есть, например. Цикл (с условием выхода) ЦП прогнозирует, что условие выхода не будет выполнено, и пытается выполнить некоторые операции внутри цикла, даже если условие еще не проверено. Если ЦП прогнозирует правильно, это экономит некоторое время, и все в порядке. Однако что произойдет, если он не сможет предсказать это правильно? Я знаю, что это приведет к снижению производительности, но я не знаю, будут ли некоторые уже выполненные операции отменены или отменены, или как они с этим справятся.
Теперь я придумал два простых примера. Первый из них (если игнорировать тот факт, что компилятор может просто вычислить сумму во время компиляции, и я предполагаю, что никакой оптимизации не происходит) должен быть очень легко предсказать для ЦП. Условие цикла будет одинаковым все время, а условие в цикле переключается только один раз. Это означает, что прогноз даст нам хороший прирост производительности, и даже если он несколько раз потерпит неудачу, добавление числа можно легко отменить.
Во втором примере условие выхода снова легко предсказать. В теле цикла я выделяю новый массив int с помощью malloc. Обратите внимание, что я не освобождаю его намеренно, так как хочу, чтобы выделение выполнялось успешно в течение длительного времени, чтобы ЦП предсказывал этот успех. В какой-то момент выделение не удастся, если у меня закончится память (я не рассчитал общее потребление памяти и предположу, что память не будет перемещена на диск) или произойдет какая-то другая ошибка. Это означает, что ptr будет иметь значение NULL и его разыменование будет UB. Неизвестно, что произойдет, это может быть просто сбой, привести к сбою моей программы или к тому, что мой компьютер улетит. Поэтому я делаю вывод, что процессор не может просто отменить это, и мне интересно, что произойдет.
#include #define ВЕРСИЯ 1 #if ВЕРСИЯ == 1 интервал основной() { size_t сумма = 0ull; for (size_t i = 0ull, max = 1'000ull; i < max; ++i) { если (я < (макс/2)) { сумма += 2 * я; } еще { сумма += я; } } вернуть 0; } #еще интервал основной() { INT* ПТР = NULL; for (size_t i = 0ull, max = 1’000’000ull; i
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Что такое неопределенное поведение при этих преобразованиях указателей? [дубликат]
Anonymous » » в форуме C++ - 0 Ответы
- 29 Просмотры
-
Последнее сообщение Anonymous
-