Есть ли метод оптимизации кода для следующей программы на C ++? - PullRequest
1 голос
/ 14 марта 2011
        BYTE * srcData;
        BYTE * pData;

        int i,j;
        int srcPadding;

                    //some variable initialization

        for (int r = 0;r < h;r++,srcData+= srcPadding)
        {
            for (int col = 0;col < w;col++,pData += 4,srcData += 3)
            {
                memcpy(pData,srcData,3);        
            }
        }

Я пробовал развернуть цикл, но это мало помогает.

        int segs = w / 4;
        int remain = w - segs * 4; 

        for (int r = 0;r < h;r++,srcData+= srcPadding)
        {
            int idx = 0;
            for (idx = 0;idx < segs;idx++,pData += 16,srcData += 12)
            {
                memcpy(pData,srcData,3);
                *(pData + 3) = 0xFF;
                memcpy(pData + 4,srcData + 3,3);
                *(pData + 7) = 0xFF;
                memcpy(pData + 8,srcData + 6,3);
                *(pData + 11) = 0xFF;
                memcpy(pData + 12,srcData + 9,3);
                *(pData + 15) = 0xFF;
            }
            for (idx = 0;idx < remain;idx++,pData += 4,srcData += 3)
            {
                memcpy(pData,srcData,3);
                *(pData + 3) = 0xFF;
            }
        }

Ответы [ 5 ]

1 голос
/ 14 марта 2011

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

uint32_t in0 = *(uint32_t*)(srcData);
uint32_t in1 = *(uint32_t*)(srcData + 4);
uint32_t in2 = *(uint32_t*)(srcData + 8);
uint32_t out0 = UINT32_C(0xFF000000) | (in0 & UINT32_C(0x00FFFFFF));
uint32_t out1 = UINT32_C(0xFF000000) | (in0 >> 24) | ((in1 & 0xFFFF) << 8);
uint32_t out2 = UINT32_C(0xFF000000) | (in1 >> 16) | ((in2 & 0xFF) << 16);
uint32_t out3 = UINT32_C(0xFF000000) | (in2 >> 8);
*(uint32_t*)(pData) = out0;
*(uint32_t*)(pData + 4) = out1;
*(uint32_t*)(pData + 8) = out2;
*(uint32_t*)(pData + 12) = out3;

Вы также должны объявить srcData и pData как BYTE * restrict указатели, чтобы компилятор знал, что они не являются псевдонимами.

0 голосов
/ 14 марта 2011

Может быть вместо цикла циклов вместо вложенных циклов:

BYTE *src = srcData;
BYTE *dest = pData;
int maxsrc = h*(w*3+srcPadding);
int offset = 0;
int maxoffset = w*3;
while (src+offset < maxsrc) {
    *dest++ = *(src+offset++);
    *dest++ = *(src+offset++);
    *dest++ = *(src+offset++);
    dest++;
    if (offset > maxoffset) {
        src += srcPadding;
        offset = 0;
    }
}
0 голосов
/ 14 марта 2011

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

0 голосов
/ 14 марта 2011

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

0 голосов
/ 14 марта 2011

Я не вижу, чтобы ты делал что-то ненужное. Вы можете изменить постинкременты на преинкременты (например, idx++ до ++idx), но это не даст ощутимого эффекта.

Кроме того, вы можете использовать std::copy вместо memcpy. std::copy имеет больше информации и теоретически может выбрать наиболее эффективный способ копирования вещей. К сожалению, я не верю, что многие реализации STL действительно используют дополнительную информацию.

Единственное, что я ожидаю, будет иметь значение, так это то, что нет никаких оснований ждать, пока один memcpy закончит, прежде чем начинать следующий. Вы можете использовать OpenMP или Intel Threading Building Blocks (или какую-то очередь потоков) для распараллеливания циклов.

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