Оптимизация

Apr 16, 2014 02:47

Цикл вида

#include
#include
int main(int argc, char *argv[]) {
int j = atoi(argv[1]);
int k = atoi(argv[2]);
int n = atoi(argv[3]);
for (int i = 0; i < n; ++i) {
j += k;
}
printf("%d\n", j);

схлопывается до printf("%d\n", j + ((n < 0) ? 0 : k*n)) в gcc 4.4.3 (а ему уже 5 лет ( Read more... )

c++

Leave a comment

Comments 27

archaicos April 15 2014, 23:45:04 UTC
Use volatiles if you want to make sure the calculations and their order are preserved.

Reply

some41 April 16 2014, 02:13:37 UTC
это будет стресс-тест обращений в память.

@_winnie: BREAKING NEWS!

Reply

archaicos April 16 2014, 02:20:40 UTC
Зависит от объёма и схемы использования переменных. Если всё влазит в кеш, стресс теста не будет. Если не влазит, так оно наверняка не влезет и без volatile. Но хоть считаться будет честно. Ещё можно напрочь отрубить оптимизацию со всеми вытекающими последствиями.

Reply

some41 April 16 2014, 02:23:47 UTC
скорость работы неоптимизированного кода с практической точки зрения довольно мало интересна. добавление большого количества volatile мало интересно по той же причине. правильно делать именно так, как написал _winnie.

Reply


kodt_rsdn April 16 2014, 02:07:56 UTC
Я для стресстеста использую 3x+1 в конечном поле. Пока эту проблему ни один компмлятор не решил…

Reply

_winnie April 19 2014, 12:01:31 UTC
Увы, C++ компиляторы решили. http://users.livejournal.com/_winnie/419241.html

Reply


levgem April 16 2014, 06:31:21 UTC
а в чём проблема в этом конкретном случае?

Reply


gegmopo4 April 16 2014, 07:39:26 UTC
Старая байка. Рассказывают о древнем компиляторе Фортрана, который соптимизировал программу, в которой не было вывода, в пустую.

Reply

archaicos April 16 2014, 09:59:53 UTC
Нормальное дело. Вон, while(1); тоже можно выкинуть, т.к. побочных эффектов, определённых в стандарте языка, у такого бесконечного цикла нету. И кое-где такое уже выкидывется.

Reply

_winnie April 16 2014, 12:52:11 UTC
Ты не хочешь жить в те времена, в которые условие цикла (1 != 2) станет ложным :)
Если из кода ниже выкинуть бесконечный цикл, то обязан сработать assert :)
while(1 != 2);
assert(1 != 2); //assertion should fail

--------
А то что выкидываются циклы
for (int i = 0; i < 10000000; ++i) ; //пауза для пользователя

это известно всем, кто переносил свой код с Паскаля и Турбо-С на Visual C/gcc :)

volatile - полезный трюк, но сильно специфичен конкретно для C++ и вдруг компилятор начнёт незаметно врать - его сложно будет поймать на вранье. А так, если вдруг имеешь дело с неким новым волшебным языком (c ленивыми вычислениями, например), способ "честно обработать данные" самый надёжный.

Reply

archaicos April 16 2014, 17:58:10 UTC
assert() обязан сработать, если аргумент нулевой, а тут - нет.

Reply


ext_2542396 April 18 2014, 12:26:58 UTC
Как этого добиться то? Вот есть функция возвращающая вводные данные похожие на реальные, скажем просто число 42, как заставить компилятор забыть о том, что ему известно об этой функции?

Reply

_winnie April 18 2014, 15:09:49 UTC
Можно взять 42 из ввода программы (из файла), самое надёжное.

Работающие в данный момент приемы:
Взять 42 из volatile переменной.
Взять 42 из глобальной переменной (компилятор не знает, вдруг после линковки другой модуль меняет её).
Вызвать функцию через volatile/глобальный указатель на функцию - она не будет инлайнится, так как компилятор не знает, что лежит в этом указателе:

void f(int i) { ... }

void (*pf)(int) = pf;

int main() {
  pf();
}

Reply


Leave a comment

Up