【问题标题】:1D Convolution without if-else statements (non-FFT)?没有 if-else 语句的一维卷积(非 FFT)?
【发布时间】:2012-09-16 14:49:45
【问题描述】:

我编写了一个简单的串行一维卷积函数(如下)。我也在试验 GPU 卷积实现。这主要是出于我自己的好奇心;我正在尝试学习各种非 FFT 实施策略之间的性能权衡。

避免分支对于我的 GPU 卷积实验很重要,因为 Nvidia GPU 上的分支成本很高。我的一个朋友提到有一种方法可以在没有if/else 语句的情况下实现下面的代码,但他不记得它是如何工作的。

如何在不使用任何if/else 语句的情况下进行正确的一维卷积实现?

这是我用 C++ 编写的基本一维串行代码:

vector<int> myConv1d(vector<int> vec, vector<int> kernel)
{
    int paddedLength = vec.size() + kernel.size() - 1;
    vector<int> convolved(paddedLength); //zeros
    reverse(kernel.begin(), kernel.end()); //flip the kernel (if we don't flip it, then we have correlation instead of convolution)
    for(int outputIdx=0; outputIdx<paddedLength; outputIdx++) //index into 'convolved' vector
    {
        int vecIdx = outputIdx - kernel.size() + 1; //aligns with leftmost element of kernel
        for(int kernelIdx=0; kernelIdx<kernel.size(); kernelIdx++)
        {
            if( (vecIdx+kernelIdx) >= 0  &&  (vecIdx+kernelIdx) < vec.size() ) //TODO: FIND A WAY TO REMOVE THIS
            {
                convolved[outputIdx] += kernel[kernelIdx]*vec[vecIdx+kernelIdx];
            }
        }
    }
    return convolved;
}

几个快速说明:

  • 我确实找到了somerelatedposts,但我不太了解避免条件语句的策略。
  • 我还编写了一个 2D 卷积实现,我希望将这篇 SO 帖子的结果也应用到 2D 版本中。
  • 这不是家庭作业。它与我们的一项研究项目略有关联,但主要是为了学习。

【问题讨论】:

  • 你打算如何在 GPU 上实现这个?在像素着色器中还是在 CUDA 中?如果在像素着色器中使用纹理查找,您能否不仅在用于数据的纹理边界处设置零并将纹理寻址模式设置为钳位?或者甚至忘记零并使用钳位寻址?

标签: c++ optimization image-processing convolution


【解决方案1】:

你为什么不做这样的事情?

int lowerBound = std::max( 0, -vecIdx );
int upperBound = std::min( kernel.size(), vec.size() - vecIdx );
for( int kernelIdx = lowerBound; kernelIdx < upperBound; kernelIdx++ )

对不起,如果我不明白这个问题。

【讨论】:

  • 等等,等一下……我发现了一个中断的案例。在 matlab 中,conv([1 2 3 4 5] , [2 4 6]) = [ 2 8 20 32 44 44 30 ]。这与我在原始问题中的代码相匹配。使用上面的最小/最大想法,我得到myConv1d([1 2 3 4 5] , [2 4 6]) = [ 6 16 28 40 52 28 10 ]。我认为有一个错误......也许是一个错误?
  • 您好像忘记在最小/最大版本中反转内核。
【解决方案2】:

对源向量进行零扩展或边框扩展以避免检查。如果源向量 V 的大小为 L,内核的大小为 K,则通过预先添加和附加 K-1 个元素来填充它。

让 L = 5 和 K = 3,你应该得到填充向量

p p v v v v v q q

其中 vs 是向量元素, ps 和 qs 是填充。请记住,GPU 工具包应该允许将源向量之外的元素限制为 0 或边界值 - 有效地使上述填充无效。

【讨论】:

  • 我以前没有做过着色器编程,但我对CUDA很熟悉。这可能是一个愚蠢的问题:“clamp”是什么意思?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-01
  • 2013-06-16
  • 1970-01-01
  • 1970-01-01
  • 2015-05-16
  • 2020-03-20
  • 2019-04-09
相关资源
最近更新 更多