Какая часть стоит больше всего с точки зрения производительности в этом C-коде? - PullRequest
0 голосов
/ 13 апреля 2019

Я должен ответить на вопрос об относительно простом фрагменте кода C-кода. В приведенной ниже функции, что будет наиболее затратным с точки зрения производительности или сложности времени? Я действительно понятия не имею, как на это ответить, потому что я чувствую, что это зависит от оператора if. Также я не знаю, является ли сравнение дорогостоящим или нет, то же самое относится и к возврату, доступу к структуре и умножению.

Кстати, info_h является структурой.

RGBPixel* bm_get_pixel_at(
    unsigned int x,
    unsigned int y,
    RGBPixel *pixel_array )
{
    int index;
    int width_with_padding = info_h.width;
    if( x >= info_h.width || y >= info_h.height ){ return &blackPixel; }
    index = (info_h.height-1 - y) * width_with_padding + x;
    return pixel_array + index;
}

EDIT:

Хорошо, вопрос мог быть немного странно сформулирован. Я должен добавить, что это только одна функция из многих в немного более сложной программе на c, которую мы уже 30 раз запускали сценарий oprofile. Затем скрипт возвращает результаты среднего времени, в течение которого каждая процедура была выбрана oprofile. В этой таблице результатов эта функция заняла третье место по выборке. Поэтому возникает вопрос: какая часть этой функции заставляет программу проводить в ней треть своего времени? Извините, если в начале было немного неясно

1 Ответ

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

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

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

static inline
RGBPixel* bm_get_pixel_at_UNSAFE(
    unsigned int x,
    unsigned int y,
    RGBPixel *pixel_array )
{
    size_t const width_with_padding = info_h.width;
    size_t const index = ((size_t)info_h.height-1 - y) * width_with_padding + x;
    return &pixel_array[index];
}

RGBPixel* bm_get_pixel_at(
    unsigned int x,
    unsigned int y,
    RGBPixel *pixel_array )
{
    return ( x < info_h.width && y < info_h.height ) ?
          bm_get_pixel_at_UNSAFE(x,y, pixel_array)
        : &blackPixel;
}

void foo(RGBPixel *pixel_array)
{
    /* iteration stays inside array bounds */
    for( unsigned int y = 0; y < info_h.height; ++y )
    for( unsigned int x = 0; x < info_h.width;  ++x ){
        RGBPixel *px = bm_get_pixel_at_UNSAFE(x, y, pixel_array);
        /* ... */
    }
}
...