2017-01-11 2 views
0

Если у нас есть деление на один во внутреннем цикле, он умен, чтобы добавить специальную обработку случая, чтобы устранить разделение:Должно ли разделение на один получить специальный случай?

ДО:

int collapseFactorDepth... 
    for (int i = 0; i < numPixels; i++) 
    { 
     pDataTarget[i] += pPixelData[i]/collapseFactorDepth; 
    } 

ПОСЛЕ:

if (collapseFactorDepth != 1) 
    { 
    for (int i = 0; i < numPixels; i++) 
    { 
     pDataTarget[i] += pPixelData[i]/collapseFactorDepth; 
    } 
    } 
    else 
    { 
    for (int i = 0; i < numPixels; i++) 
    { 
     pDataTarget[i] += pPixelData[i]; 
    } 
    } 

Может компилятор рассуждает это сам по себе? У современных процессоров есть какие-либо средства для оптимизации этого?

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

фона:

  • Numpixels большой
  • collapseFactorDepth составляет 90% от времени 1
  • современных процессоров: Intel x86/amd64 архитектуры
  • Пожалуйста, не учитывают более широкие вещи. Оптимизирована нагрузка памяти на загрузку.
  • Не будем вспотеть, что мы должны, вероятно, сделать это как двойное умножение.
+1

Как раз моя мысль, если вызывающий человек хочет разделить на один, просто сделайте это. (Вероятно, я не буду проверять «0») –

+0

Это была бы преждевременная оптимизация. Когда вы оптимизируете одно, вы пессимизируете все остальное. Гораздо важнее ясность кода. –

+0

Просто FYI, если вы зададите такой вопрос производительности, и вы знаете, что вы делаете, обычно полезно дать некоторый опыт самой проблеме производительности. В противном случае вы просто получите кучу (потенциально бесполезных) комментариев и ответов, говорящих вам не оптимизировать вообще. – Mysticial

ответ

2

Как правило, ответ No. Сначала напишите чистый код и оптимизируйте его позже, когда профайлер говорит, что у вас есть проблема.

Единственный способ ответить, поможет ли эта конкретная оптимизация в этой конкретной точке доступа: «измерить ее и увидеть».

Если только collapseFactorDepthпочти всегда 1 или numPixels очень велико (по крайней мере, тысячи и, возможно, больше), я бы не стал ожидать оптимизации, чтобы помочь (ветви дорого).

У вас гораздо больше шансов воспользоваться SSE или аналогичными инструкциями SIMD.

+0

CollapseDepthFactor почти всегда 1 (97%) времени, но я бы не хотел дублировать код, если это не приводит к повышению производительности. –

+0

NumPixels обычно большой 512x512 до полного HD –

+0

Хмм. Если NumPixels велико, ваша следующая проблема заключается в том, что вы должны получить все эти данные из памяти в CPU и обратно; моя интуиция заключается в том, что пропускная способность памяти, вероятно, будет доминирующим фактором - так что оптимизация точек не будет. Обратите внимание, что моя интуиция о производительности была правильной примерно три раза за последние 35 лет *** *** *** *** –

0
  1. Следуйте совету @Martin Bonner. Оптимизируйте, когда вам нужно.
  2. Когда вам нужно:

int identity(int pixel) 
{ 
    return pixel; 
} 

template<int collapseFactorDepth> 
int div(int pixel) 
{ 
    return pixel/collapseFactorDepth; 
} 

struct Div 
{ 
    int collapseFactorDepth_; 
    Div(collapseFactorDepth) 
     : collapseFactorDepth(collapseFactorDepth_) {} 
    int operator()(int pixel) 
    { 
     return pixel/collapseFactorDepth_; 
    } 
}; 

template<typename T> 
void fn(int* pDataTarget, T fn) 
{  
    for (int i = 0; i < numPixels; i++) 
    { 
     pDataTarget[i] += fn(pPixelData[i]); 
    } 
} 

void fn(int* pDataTarget) 
{ 
    fn(pDataTarget, identity); 
} 

template<int collapseFactorDepth> 
void fnComp() 
{ 
    fn(pDataTarget, div<collapseFactorDepth>); 
} 

void fn(int* pDataTarget, int collapseFactorDepth) 
{ 
    fn(pDataTarget, Div(collapseFactorDepth)); 
} 

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

Смежные вопросы