我试图优化非常大的图像的旋转中心任意角度,最小的是4096×4096或〜1600万像素。优化旋转矩阵 - 关于矩阵
旋转总是关于图像的中心和图像不一定总是正方形的,但永远是2
我有机会获得MKL/TBB,其中MKL是一个优化的BLAS我的目标动力平台。我不熟悉这个操作是否在BLAS中。所以,裸露在我面前的答案是显而易见的,只是我不熟悉的BLAS功能。
我尽了最大努力,到目前为止都是围绕17-25ms为4096×4096的图像(相同的图像尺寸,这意味着我可能踩遍缓存很不一致)。矩阵是16字节对齐的。现在
,目标不能调整大小。所以,裁剪应该会发生。例如,以45度角旋转的矩形矩阵必定会夹在角上,该位置的值应为零。
现在,我尽了最大努力用瓷砖的做法 - 不优雅是尚未被放入片大小也不循环展开。
这里是我的算法,因为它代表利用TBB - http://threadingbuildingblocks.org/:
//- cosa = cos of the angle
//- sina = sin of angle
//- for those unfamiliar with TBB, this is giving me blocks of rows or cols that
//- are unique per thread
void operator() (const tbb::blocked_range2d<size_t, size_t> r) const
{
double xOffset;
double yOffset;
int lineOffset;
int srcX;
int srcY;
for (size_t row = r.rows().begin(); row != r.rows().end(); ++row)
{
const size_t colBegin = r.cols().begin();
xOffset = -(row * sina) + xHelper + (cosa * colBegin);
yOffset = (row * cosa) + yHelper + (sina * colBegin);
lineOffset = (row * rowSpan); //- all col values are offsets of this row
for(size_t col = colBegin; col != r.cols().end(); ++col, xOffset += cosa, yOffset += sina)
{
srcX = xOffset;
srcY = yOffset;
if(srcX >= 0 && srcX < colSpan && srcY >= 0 && srcY < rowSpan)
{
destData[col + lineOffset] = srcData[srcX + (srcY * rowSpan)];
}
}
}
}
我对这个函数的调用是这样的:
double sina = sin(angle);
double cosa = cos(angle);
double centerX = (colSpan)/2;
double centerY = (rowSpan)/2;
//- Adding .5 for rounding
const double xHelper = centerX - (centerX * cosa) + (centerY * sina) + .5;
const double yHelper = centerY - (centerX * sina) - (centerY * cosa) + .5;
tbb::parallel_for(tbb::blocked_range2d<size_t, size_t>(0, rowSpan, 0, colSpan), DoRotate(sina, cosa, xHelper, yHelper, rowSpan, colSpan, (fcomplex *)pDestData, (fcomplex *)pSrcData));
浮点型复数仅仅是在复数的房子表示。它被定义为:
struct fcomplex
{
float real;
float imag;
};
所以,我想要做复数值矩阵的绕它的中心在任意角度非常大的图像尽可能快。
更新:
基于奇妙的反馈,我已经更新到这一点:这是增加约40%。我想知道,但如果什么都可以做:
void operator() (const tbb::blocked_range2d<size_t, size_t> r) const
{
float xOffset;
float yOffset;
int lineOffset;
__m128i srcXints;
__m128i srcYints;
__m128 dupXOffset;
__m128 dupYOffset;
for (size_t row = r.rows().begin(); row != r.rows().end(); ++row)
{
const size_t colBegin = r.cols().begin();
xOffset = -(row * sina) + xHelper + (cosa * colBegin);
yOffset = (row * cosa) + yHelper + (sina * colBegin);
lineOffset = (row * rowSpan); //- all col values are offsets of this row
for(size_t col = colBegin; col != r.cols().end(); col+=4, xOffset += dupOffsetsX.m128_f32[3], yOffset += dupOffsetsY.m128_f32[3])
{
dupXOffset = _mm_load1_ps(&xOffset); //- duplicate the x offset 4 times into a 4 float field
dupYOffset = _mm_load1_ps(&yOffset); //- duplicate the y offset 4 times into a 4 float field
srcXints = _mm_cvtps_epi32(_mm_add_ps(dupOffsetsX, dupXOffset));
srcYints = _mm_cvtps_epi32(_mm_add_ps(dupOffsetsY, dupYOffset));
if(srcXints.m128i_i32[0] >= 0 && srcXints.m128i_i32[0] < colSpan && srcYints.m128i_i32[0] >= 0 && srcYints.m128i_i32[0] < rowSpan)
{
destData[col + lineOffset] = srcData[srcXints.m128i_i32[0] + (srcYints.m128i_i32[0] * rowSpan)];
}
if(srcXints.m128i_i32[1] >= 0 && srcXints.m128i_i32[1] < colSpan && srcYints.m128i_i32[1] >= 0 && srcYints.m128i_i32[1] < rowSpan)
{
destData[col + 1 + lineOffset] = srcData[srcXints.m128i_i32[1] + (srcYints.m128i_i32[1] * rowSpan)];
}
if(srcXints.m128i_i32[2] >= 0 && srcXints.m128i_i32[2] < colSpan && srcYints.m128i_i32[2] >= 0 && srcYints.m128i_i32[2] < rowSpan)
{
destData[col + 2 + lineOffset] = srcData[srcXints.m128i_i32[2] + (srcYints.m128i_i32[2] * rowSpan)];
}
if(srcXints.m128i_i32[3] >= 0 && srcXints.m128i_i32[3] < colSpan && srcYints.m128i_i32[3] >= 0 && srcYints.m128i_i32[3] < rowSpan)
{
destData[col + 3 + lineOffset] = srcData[srcXints.m128i_i32[3] + (srcYints.m128i_i32[3] * rowSpan)];
}
}
}
}
更新2: 我把下面的解决方案,同时考虑到建议我得到的答案以及旋转矩形时修复bug。
I [编辑了杂波](http://meta.stackexchange.com/questions/2950/should-hi-thanks-taglines-and-salutations-be-removed-from-posts)一个第二时间。 – Bart
这为GPU计算而尖叫。也许这对你来说是一种选择。 –
我记得在人杰地灵使用[布氏算法(http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm),以避免浮点运算在这样的背景下。这可能是一个想法,因为您的xOffset和yOffset修改似乎是Bresenham的理想选择。 –