我想加快我的c ++双线性插值代码。
设置如下:从灰度图像 img 我想在 cent 位置提取矩形补丁 pat 单位间距,没有上/下采样。</ strong>
由于 cent 通常不是整数,我必须双线插值提取的补丁。
图像 img ,提取的补丁 pat 和位置 cent 存储为浮点数。 补丁的大小为[2 * pad + 1], pad 是位置 cent 的左右填充。
目前的解决方案如下:
void function(Eigen::Matrix<float, Eigen::Dynamic, 1>* pat,
const float* img,
const Eigen::Vector2f* cent)
{
Eigen::Vector4f we; // bilinear weight vector
// ... [CROPPED: compute bilinear weights]
float *pat_it = pat->data();
for (y=cent[1]-pad; y <= cent[1]+pad; ++y)
{
int postmp_a = y * image_width;
int postmp_b = (y-1) * image_width;
for (x=cent[0]-pad; x <= cent[0]+pad; ++x, ++pat_it)
{
(*pat_it) = we[0] * img[ x + postmp_a] +
we[1] * img[x-1 + postmp_a] +
we[2] * img[ x + postmp_b] +
we[3] * img[x-1 + postmp_b];
}
}
}
是否可以进一步提高速度?此功能将在实时信号处理管道中被调用数百万次。 没有内存限制。
是否可能有特定的特征函数?
由于这是我的代码最关键的瓶颈,我也愿意考虑将代码移动到不同的编程语言/架构(汇编程序,CUDA等......)。有关于此的任何想法/提示吗?
更一般地说,您如何系统地对此进行分析?
更多细节:代码使用'-Ofast -std = c ++ 11'编译,并且已经使用OpenMP并行运行。图像大小约为~1000x1200像素, pad 在5-10像素之间。
修改
通过直接使用指向4个相应图像位置的指针,我已经设法提高了约6%的速度。
...
for (x=cent[0]-pad; x <= cent[0]+pad; ++x,++pat_it,
++img_a,++img_b,++img_c,++img_d)
{
(*pat_it) = we[0] * (*img_a) +
we[1] * (*img_b) +
we[2] * (*img_c) +
we[3] * (*img_d);
}
...
答案 0 :(得分:1)
您可以尝试让Eigen简化其中的一些内容,例如:
void function(Eigen::VectorXf* pat,
const float* img,
const Eigen::Vector2f* cent)
{
...
for (y=cent[1]-pad; y <= cent[1]+pad; ++y)
{
...
Eigen::Map<Eigen::Array4f, 0, Eigen::OuterStride<>> mp(img + cent[0]-pad -1 + postmp_b, 4, Eigen::OuterStride<>(image_width));
for (x=cent[0]-pad; x <= cent[0]+pad; ++x, ++pat_it)
{
new (&mp) Eigen::Map<Eigen::Array4f>(img + x-1 + postmp_b, 4, Eigen::OuterStride<>(image_width));
(*pat_it) = (mp * we.array()).sum();
...
注意:您可能需要重新排列we
以匹配img
元素的新顺序。
你可以通过不创建一堆地图来尝试做得更好,而是创建一个大的地图:
void function(Eigen::VectorXf* pat,
const float* img,
const Eigen::Vector2f* cent)
{
...
Eigen::Map<Eigen::ArrayXXf, 0, Eigen::OuterStride<>> mp(img, image_width, image_height, Eigen::OuterStride<>(image_width));
for (y=cent[1]-pad; y <= cent[1]+pad; ++y)
{
...
for (x=cent[0]-pad; x <= cent[0]+pad; ++x, ++pat_it)
{
(*pat_it) = (mp.block<2,2>(x,y) * we.array()).sum();
...
你可能会做得更好,我还没有测试过这些。这导致我发出以下免责声明。我还没有测试过这个。这意味着,您可能需要更改InnerStride
和OuterStride
以及image_width
和image_height
等。
如果这对你有所帮助,我很想知道它给了多少加速。