【问题标题】:Is there any code Optimization method for the following c++ program下面c++程序有没有代码优化方法
【发布时间】:2011-03-14 05:19:32
【问题描述】:
        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;
            }
        }

【问题讨论】:

  • 我不确定整体算法,但如果你没有在语句中使用之前的值,你应该使用预增量,所以使用 ++idx 和 ++r。尽管打开了任何优化,编译器可能会为您执行此操作。

标签: c++ optimization loops for-loop


【解决方案1】:

根据您的编译器,您可能根本不需要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;

您还应该将srcDatapData 声明为BYTE * restrict 指针,以便编译器知道它们没有别名。

【讨论】:

    【解决方案2】:

    我不认为你这样做是不必要的。您可以将后增量更改为前增量(例如,idx++++idx),但这不会产生可衡量的效果。

    此外,您可以使用std::copy 代替memcpystd::copy 有更多可用信息,理论上可以选择最有效的复制方式。不幸的是,我不相信许多 STL 实现实际上会利用额外的信息。

    我唯一期望会有所作为的是,没有理由在开始下一个之前等待一个 memcpy 完成。您可以使用 OpenMP 或 Intel Threading Building Blocks(或某种线程队列)来并行化循环。

    【讨论】:

      【解决方案3】:

      不要调用 memcpy,直接手动复制即可。除非您一次可以复制超过 3 个字节,否则函数调用开销是不值得的。

      【讨论】:

      • 我相信这取决于编译器。例如,我认为 GCC 会内联小型、固定大小的 memcpy 调用。
      • @Jeremiah 可能是真的,但为什么要编写依赖于 GCC 的某些版本/标志的代码呢?
      【解决方案4】:

      就这个特定的循环而言,您可能想了解一种称为Duff's device 的技术,它是一种利用开关构造的循环展开技术。

      【讨论】:

        【解决方案5】:

        也许改成 while 循环而不是嵌套的 for 循环:

        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;
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-02-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多