Повторение одного и того же сегмента кода 1000 раз без цикла - PullRequest
0 голосов
/ 30 апреля 2019

По какой-то причине (связанной с измерениями производительности) мне нужно повторить сегмент кода 1000 раз (1024 раза тоже было бы нормально), но БЕЗ "для" или любого другого цикла.

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

#define RUN_1000_TIMES(x)   \
x                           \
x                           \
x                           \
...
...  /* (999+1 times the same line) */
...
x                           \
x

... и затем применить этот макрос к моему сегменту кода.

Но есть ли более элегантное решение, чем 1000Макрос длинных строк?

Ответы [ 5 ]

3 голосов
/ 30 апреля 2019
#define RUN_1024_TIMES(x) do {RUN_512_TIMES(x); RUN_512_TIMES(x); } while(0)
#define RUN_512_TIMES(x) do {RUN_256_TIMES(x); RUN_256_TIMES(x); } while(0)
#define RUN_256_TIMES(x) do {RUN_128_TIMES(x); RUN_128_TIMES(x); } while(0)
#define RUN_128_TIMES(x) do {RUN_64_TIMES(x); RUN_64_TIMES(x); } while(0)
#define RUN_64_TIMES(x) do {RUN_32_TIMES(x); RUN_32_TIMES(x); } while(0)
#define RUN_32_TIMES(x) do {RUN_16_TIMES(x); RUN_16_TIMES(x); } while(0)
#define RUN_16_TIMES(x) do {RUN_8_TIMES(x); RUN_8_TIMES(x); } while(0)
#define RUN_8_TIMES(x) do {RUN_4_TIMES(x); RUN_4_TIMES(x); } while(0)
#define RUN_4_TIMES(x) do {RUN_2_TIMES(x); RUN_2_TIMES(x); } while(0)
#define RUN_2_TIMES(x) do {x; x; } while(0)

do{ ... } while(0) только для случая, когда вы называете его if (....) RUN_1024_TIMES(...);.Вы можете удалить его, когда вам это не нужно.

Вы также можете сделать это 3 раза за макрос:

#define RUN_1000_TIMES(x) do {RUN_729_TIMES(x); RUN_243_TIMES(x); RUN_27_TIMES(x); x; } while(0)
#define RUN_729_TIMES(x) do {RUN_243_TIMES(x); RUN_243_TIMES(x); RUN_243_TIMES(x); } while(0)
#define RUN_243_TIMES(x) do {RUN_81_TIMES(x); RUN_81_TIMES(x); RUN_81_TIMES(x); } while(0)
#define RUN_81_TIMES(x) do {RUN_27_TIMES(x); RUN_27_TIMES(x); RUN_27_TIMES(x); } while(0)
#define RUN_27_TIMES(x) do {RUN_9_TIMES(x); RUN_9_TIMES(x); RUN_9_TIMES(x); } while(0)
#define RUN_9_TIMES(x) do {RUN_3_TIMES(x); RUN_3_TIMES(x); RUN_3_TIMES(x); } while(0)
#define RUN_3_TIMES(x) do {x; x; x; } while(0)
1 голос
/ 01 мая 2019

Для этого вы можете использовать P99: http://p99.gforge.inria.fr/p99-html/group__preprocessor__for_gaec0c87b336a5fa2a8230e207af5cc1f0.html#gaec0c87b336a5fa2a8230e207af5cc1f0

"Грустная" часть в том, что, возможно, достаточно умный компилятор ... сделайте это циклом!

1 голос
/ 30 апреля 2019
#define RUN_10_TIMES(X) X X X X X X X X X X
#define RUN_1000_TIMES(X) RUN_10_TIMES(RUN_10_TIMES(RUN_10_TIMES(X)))

Обратите внимание, что вы можете рекурсивно "вызывать" макрос в "вызове", как синтаксис (так что FOO(FOO(FOO(X))) нормально);это связано с тем, что на первом этапе вызова функции, подобного макросу, используется подстановка аргумента , который не имеет ограничений на рекурсию.Подстановка аргумента, в частности, включает в себя оценку любого аргумента, соответствующий параметр которого появляется в списке замены (и не является строковым или частью вставки), как если бы он был в отдельной строке, а затем использует результирующее расширение для замены каждого такого параметра.После подстановки аргумента (и вставки / строкового преобразования) результирующий список замен повторно сканируется с повторным сканированием и последующим этапом замены ;во время этого шага макрос помечается «синей краской» (то есть дополнительные вызовы игнорируются).Подобная вызову рекурсия полностью является функцией подстановки аргумента, поэтому она разрешена.

1 голос
/ 30 апреля 2019

в файле Python, поместите:

print("//header of the code")
for i in range(1000):
    print("x;")
print("//bottom of the code")

и затем:

./gen.py > file.c

это будет проще, чем то, что вы можете сделать с препроцессором C, которое не может выполнять такие вещи, как цикл!

0 голосов
/ 30 апреля 2019

Вы можете написать свои циклы в обычном режиме, а затем просто сказать компилятору, что хотите, чтобы циклы были развернуты.Это хорошо написано, и так же оптимально, как если бы вы написали 1000 строк.

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

Если вы хотите развернуть все циклы в вашем коде, это проще: вам просто нужно добавитьВариант или два в командной строке:

-funroll-loops
-funroll-all-loops

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

Если вы просто хотите развернуть определенный цикл и сохранить все остальные циклы, это сложнее, но это также можно сделать.Проверьте этот SO ответ на этот вопрос: https://stackoverflow.com/a/14251545/6872717

...