簡単なシリアル 1D 畳み込み関数を作成しました (以下)。GPU 畳み込みの実装も試しています。これは主に私自身の好奇心によるものです。さまざまな非FFT実装戦略間のパフォーマンスのトレードオフを学ぼうとしています。
Nvidia GPU では分岐はコストがかかるため、GPU 畳み込みの実験では分岐を回避することが重要です。私の友人の 1 人が、以下のコードをif/else
ステートメントなしで実装する方法があると言いましたが、彼はそれがどのように機能するか思い出せませんでした。
if/else
ステートメントを使用せずに正しい 1D 畳み込みを実装するにはどうすればよいですか?
C++ での基本的な 1D シリアル コードは次のとおりです。
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;
}
いくつかの簡単なメモ: