2013-04-11 84 views
5

我有一个简单的算法,将拜耳图像通道(BGGR,RGGB,GBRG,GRBG)转换为rgb(去马赛克但没有邻居)。在我的实现中,我有预先设置的偏移向量,这有助于我将拜耳通道索引转换为相应的rgb通道索引。 唯一的问题是我在MSVC11的调试模式下性能不佳。在发布时,对于3264X2540大小的输入,该功能在〜60ms内完成。对于调试中的相同输入,该功能在〜20,000ms内完成。这比X300的差别更大,因为有些开发人员在调试中运行我的应用程序,这是不可接受的。剧烈的性能差异:调试与发布

我的代码:

void ConvertBayerToRgbImageDemosaic(int* BayerChannel, int* RgbChannel, int Width, int 

Height, ColorSpace ColorSpace) 
{ 
    int rgbOffsets[4]; //translates color location in Bayer block to it's location in RGB block. So R->0, G->1, B->2 
    std::vector<int> bayerToRgbOffsets[4]; //the offsets from every color in the Bayer block to (bayer) indices it will be copied to (R,B are copied to all indices, Gr to R and Gb to B). 
    //calculate offsets according to color space 
    switch (ColorSpace) 
    { 
    case ColorSpace::BGGR: 
      /* 
      B G 
      G R 
      */ 
     rgbOffsets[0] = 2; //B->0 
     rgbOffsets[1] = 1; //G->1 
     rgbOffsets[2] = 1; //G->1 
     rgbOffsets[3] = 0; //R->0 
     //B is copied to every pixel in it's block 
     bayerToRgbOffsets[0].push_back(0); 
     bayerToRgbOffsets[0].push_back(1); 
     bayerToRgbOffsets[0].push_back(Width); 
     bayerToRgbOffsets[0].push_back(Width + 1); 
     //Gb is copied to it's neighbouring B 
     bayerToRgbOffsets[1].push_back(-1); 
     bayerToRgbOffsets[1].push_back(0); 
     //GR is copied to it's neighbouring R 
     bayerToRgbOffsets[2].push_back(0); 
     bayerToRgbOffsets[2].push_back(1); 
     //R is copied to every pixel in it's block 
     bayerToRgbOffsets[3].push_back(-Width - 1); 
     bayerToRgbOffsets[3].push_back(-Width); 
     bayerToRgbOffsets[3].push_back(-1); 
     bayerToRgbOffsets[3].push_back(0); 
     break; 
    ... other color spaces 
    } 

    for (auto row = 0; row < Height; row++) 
    { 
     for (auto col = 0, bayerIndex = row * Width; col < Width; col++, bayerIndex++) 
     { 
      auto colorIndex = (row%2)*2 + (col%2); //0...3, For example in BGGR: 0->B, 1->Gb, 2->Gr, 3->R 
      //iteration over bayerToRgbOffsets is O(1) since it is either sized 2 or 4. 
      std::for_each(bayerToRgbOffsets[colorIndex].begin(), bayerToRgbOffsets[colorIndex].end(), 
       [&](int colorOffset) 
       { 
        auto rgbIndex = (bayerIndex + colorOffset) * 3 + rgbOffsets[offset]; 
        RgbChannel[rgbIndex] = BayerChannel[bayerIndex]; 
       }); 
     } 
    } 
} 

我已经试过: 我试着优化图灵(/ O2)的调试版本,没有显著差异。 我试图用普通旧for循环替换内部for_each声明,但无济于事。我有一个非常相似的算法,它将bayer转换为“绿色”rgb(没有将数据复制到块中的相邻像素),其中我没有使用std::vector,并且在调试和发布之间存在期望的运行时间差异(X2- X3)。那么,std::vector会成为问题吗?如果是这样,我该如何克服它?

+5

我不明白。有什么问题?这是完全正常的,预期的和可以接受的,DEBUG模式将比释放模式慢得多。这就是为什么你有两种不同的模式。调试模式包含很多(真的很多)信息(元数据)用于调试目的。 – 2013-04-11 13:07:52

+1

@KirilKirov调试很有用,但通常时间太慢而无法使用。那就是问题所在。所以你想选择性地启用它,仅限于感兴趣的组件。这是解决方案。 – 2013-04-11 13:15:55

+0

@KirilKirov:我期望调试和发布之间的性能差异,但我从未遇到过X300的性能差异。我的算法是对输入的简单迭代。我期望在我看到的时间 – eladidan 2013-04-11 13:31:53

回答

14

当您使用std::vector时,它将有助于禁用迭代器调试。

MSDN shows how to do it.

简单来说,让这个#define您包括任何STL头前:

#define _HAS_ITERATOR_DEBUGGING 0 

根据我的经验,这给在调试的性能主要推动建立,当然,你确实会失去一些调试功能。

+0

+1。我相信这是造成差异的主要原因,很好的答案。 – 2013-04-11 13:13:22

+0

@MatsPetersson这就是C++和STL的“美”。程序中的单行可能隐藏了很多东西。有时候这些东西非常昂贵。 – 2013-04-11 13:18:23

+0

不错,我确定会是这样,但它没有帮助...任何其他想法? – eladidan 2013-04-11 13:32:35

0

在VS中,您可以使用以下设置进行调试,禁用(/ Od)。选择其中一个选项(最小尺寸(/ O1),最大速度(/ O2),完全优化(/ Ox)或自定义)。随着罗杰罗兰提到的迭代器优化...

+0

正如我在我的文章中提到的,我尝试使用/ O2但没有显着差异 – eladidan 2013-04-11 13:47:33