Как я могу выполнить оптимизацию кода в следующей программе? - PullRequest
1 голос
/ 09 сентября 2010
func()
{
fun1();
fun2();
fun3();
fun4();
fun5();
fun6();
..
..
..
..
fun99();
fun100();
}

с помощью указателей функций в программе на C?Мне нужно повторно вызывать эту программу в моей программе.

Ответы [ 8 ]

7 голосов
/ 09 сентября 2010

Не уверен, что это действительно оптимизация , но вы используете указатели функций следующим образом:

#include <stdio.h>

static void fun1 (void) {
    printf ("1\n");
}
static void fun2 (void) {
    printf ("2\n");
}
static void fun3 (void) {
    printf ("3\n");
}

static void (*fn[])(void) = {
    fun1, fun2, fun3
};

int main (void) {
    int i;
    for (i = 0; i < sizeof(fn) / sizeof(*fn); i++) {
        (fn[i])();
    }
    return 0;
}

Это выводит:

1
2
3

, как и ожидалось.

Лучшее, на что вы можете надеяться, это то, что main может быть немного меньше, но это компенсируется тем фактом, что вам нужна таблица функций.

Это полезно в разделе "Как работает C"?»в некотором роде, но не очень полезный в реальном мире.

Конечно, сами указатели функций полезны, я их довольно часто использовал для создания конечных автоматов и объектно-ориентированного кода на C. Просто этот специфическийпример кажется надуманным.

Если вы хотите выполнять их непрерывно, вы можете использовать:

int main (void) {
    int i = 0;
    while (1) {
        (fn[i])();
        i = (i + 1) % (sizeof(fn) / sizeof(*fn));
    }
    return 0;
}

, но было бы так же хорошо обернуть предыдущий цикл for внутри while (1) в любом случае.

6 голосов
/ 09 сентября 2010

Зачем вам это нужно?

А что вы хотите оптимизировать? Размер кода? Время выполнения? Я бы позволил компилятору позаботиться об этом за меня (возможно, намекнув на некоторые параметры компилятора).

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

Я предпочитаю оптимизировать мой код для удобства чтения и обслуживания.

Как всегда, мммм

3 голосов
/ 09 сентября 2010

Использование указателей функций для этого вряд ли даст вам оптимизацию скорости.Во-первых, вы бы добавили 100 указателей на функции.Во-вторых, теперь функции должны вызываться через косвенное обращение к памяти, которое медленнее, чем прямой вызов.В-третьих, вашему компилятору будет сложнее выполнять встраивание функций.

Специфика влияния на производительность будет зависеть от компилятора и целевой платформы, но для x86 вы действительно не хотите идти по пути указателя на функциюесли функции не принимают достаточное количество идентичных параметров.И если вы хотите действительно оптимизировать, для удобства чтения и скорости, вам нужно рефакторинг .

РЕДАКТИРОВАТЬ

Если мы предполагаем 32-битный x86 и обычный компилятор, ивсе функции, не принимающие аргументов, выполнение 100 последовательных вызовов займет 500 байтов на сайте вызова, поскольку вызов кодируется как E8 + четырехбайтовое смещение eip-адреса назначения.

Преобразование в указатели функций завершитсяс таблицей указателей, занимающей 400 байт (возможно, это может быть закодировано меньше, но, поскольку нам не сказано, где определен funcNNN и компилятор, я предположу 100 стандартных 32-битных указателей).В дополнение к этому, вам нужен код для перебора массива указателей и вызова функций;этот код зависит от вашего компилятора, сгенерированный код Visual C ++ 2010 составляет 16 байт.Таким образом, вы сэкономили всего 84 байта за счет скорости выполнения.

Не зная больше о вызываемых функциях, комментировать намного сложнее.

3 голосов
/ 09 сентября 2010

Если какая-либо из функций fun<i>n</i> () короткая, вы можете воспользоваться , если она встроена .Вам нужно просмотреть документацию по вашему компилятору и проверить, поддерживает ли он какие-либо явные подсказки программиста о том, какие функции следует встроить.Думаю, иногда может помочь простое создание функций static.

Конечно, встраивание удаляет только накладные расходы кода из фактического вызова функции, что (в зависимости от функций) может быть очень малой частьюобщее время выполнения.

3 голосов
/ 09 сентября 2010

Оптимизировать особо нечего. Вы можете создать инициализированный массив из 100 указателей на функции и выполнять их итерацию. Это может уменьшить размер объектного кода немного, но не намного, и будет немного медленнее, чем 100 прямых вызовов (но не намного).

void func(void)
{
    static const void (*functions[])(void) =
    {
        fun1,  fun2,  fun3,  ..., fun10,
        ...
        fun91, fun92, fun93, ..., fun100
    }
    for (int i = 0; i < 100; i++)
         (*functions[i])();
}
2 голосов
/ 09 сентября 2010
cc -O3 ......................

Будет оптимизировать это более эффективно, чем любой человек.

2 голосов
/ 09 сентября 2010

Производительность этого кода, скорее всего, будет зависеть от выполнения содержимого каждой функции, поэтому на этом уровне оптимизировать практически нечего. Одна очевидная оптимизация - поместить весь этот контент в функцию one ; но это не может быть значительным.

Если честно; если бы я увидел такой код, я бы задал серьезные вопросы о дизайне, прежде чем пытаться оптимизировать исполнение. Это не означает, что есть лучшее решение, просто выглядит он необычно , поэтому возникает вопрос.

1 голос
/ 09 сентября 2010

Как указано выше, он просто оптимизирует размер кода, readbality в main (), а не любое реальное улучшение производительности. Я не мог понять, какой вид оптимизации он действительно хочет. Пожалуйста, уточните?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...