Ускорить программу C без использования условной компиляции - PullRequest
3 голосов
/ 18 января 2012

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

Вот очень искусственный пример, демонстрирующий эффект:

/* program_define */

#include <stdio.h>
#include <stdlib.h>

#define skip 10

int main(int argc, char** argv) {
    int i, j;
    long result = 0;

    int limit = atoi(argv[1]);

    for (i = 0; i < 10000000; ++i) {
        for (j = 0; j < limit; ++j) {
            if (i + j % skip == 0) {
                continue;
            }
            result  += i + j;
        }
    }

    printf("%lu\n", result);
    return 0;
}

Здесь переменная skip является примером значения, которое влияет на поведение программы. К сожалению, нам нужно перекомпилировать каждый раз, когда мы хотим новое значение skip.

Давайте посмотрим на другую версию программы:

/* program_variable */

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
    int i, j;
    long result = 0;

    int limit = atoi(argv[1]);
    int skip = atoi(argv[2]);

    for (i = 0; i < 10000000; ++i) {
        for (j = 0; j < limit; ++j) {
            if (i + j % skip == 0) {
                continue;
            }
            result  += i + j;
        }
    }

    printf("%lu\n", result);
    return 0;
}

Здесь значение для skip передается в качестве параметра командной строки. Это добавляет большую гибкость. Однако эта программа намного медленнее:

$ time ./program_define 1000 10
50004989999950500

real 0m25.973s
user 0m25.937s
sys  0m0.019s

против

$ time ./program_variable 1000 10
50004989999950500

real 0m50.829s
user 0m50.738s
sys  0m0.042s

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

Любая помощь очень ценится!


Комментарии:

Как писал Дирк в своем комментарии 1028 *, , речь идет не о конкретном примере . Я имел в виду способ заменить if, который вычисляет переменную, которая устанавливается один раз, а затем никогда не изменяется (скажем, параметр командной строки) внутри функции, которая вызывается буквально миллиардов раз более эффективная конструкция. В настоящее время мы используем препроцессор для настройки желаемой версии функции. Было бы неплохо, если есть более хороший способ, не требующий перекомпиляции.

Ответы [ 11 ]

0 голосов
/ 18 января 2012

Возможно, вы компилируете без оптимизации, что приведет к тому, что ваша программа будет загружать пропуск каждый раз, когда проверяется, вместо литерала 10. Попробуйте добавить -O2 в командную строку вашего компилятора и / или использовать

register int skip;
...