这段代码在嵌套循环中运行9600次,每次运行的时间都不到30 is,并且必须在iPhone4S上运行:
vImage_Buffer source = { sourceArea.data, patchSide, patchSide, patchSide };
vImage_Buffer destination = { (uchar*)malloc(patchSide * patchSide * sizeof(uchar)), patchSide, patchSide, patchSide };
vImage_AffineTransform transform = { warpingMatrix(0,0), warpingMatrix(0,1), warpingMatrix(1,0), warpingMatrix(1,1), 0, 0 };
if (vImageAffineWarp_Planar8(&source, &destination, NULL, &transform, 0, kvImageBackgroundColorFill) != kvImageNoError)
{
NSLog(@"Error in warping!");
}它看起来没有那么快,因为10x10补丁大约需要0.0002秒。我是不是忽略了一些重大的表演错误?
我想要解决的问题是向后扭曲图像的匹配,这是第一步。该补丁是扭曲64次在64个不同的位置围绕一个点,每一个最大150点。
发布于 2014-08-16 18:42:18
10x10是一个非常小的图像。您可以轻松地将大部分时间花在开销/ malloc上。仪器的时间跟踪应该有助于确定时间的去向。
4s上的矢量ALU也是5或5s宽度的一半,因此不能提供比标量更大的胜利。
发布于 2014-08-16 22:06:46
如果能重用缓冲区,可见效果会更快。因此,如果可能的话,在循环之外声明和分配缓冲区(或相关数据)。
unsigned char *sourceData = (unsigned char*)malloc(patchSide * patchSide * sizeof(uchar));
vImage_Buffer source = {sourceData, patchSide, patchSide, patchSide};
unsigned char *destinationData = (unsigned char*)malloc(patchSide * patchSide * sizeof(uchar));
vImage_Buffer destination = {destinationData, patchSide, patchSide, patchSide};
loop{
//fill sourceData e.g. through memcpy
memcpy(sourceData, somedata, patchSide * patchSide * sizeof(uchar));
if (vImageAffineWarp_Planar8(&source, &destination, NULL, &transform, 0, kvImageBackgroundColorFill) != kvImageNoError)
{
NSLog(@"Error in warping!");
}
//destinationData contains the result
}发布于 2015-04-01 11:44:01
在不对代码进行太多更改的情况下,您可能需要进行两项更改来提高性能:使用vImage框架分配源/目标缓冲区和创建临时缓冲区以便在循环中重用。第三个改变可能是改变你的瓷砖大小(见这个答案的结尾)。
vImage/ your框架的文档建议使用vImageBuffer_Init (参见vImage_Utilities.h)初始化缓冲区,以确保实际的缓冲区是
大小和对齐,以获得最佳性能
而不是自己分配内存:
vImage_Buffer buffer;
vImage_Error err = vImageBuffer_Init(&buffer, height, width, 8 * sizeof(pixel), kvImageNoFlags);在您的例子中,pixel将是Pixel_8,因为您使用的是*_Planar8函数。注意,当您完成buffer.data时,仍然需要释放它。
因此,您应该在循环之外初始化源和目标:
vImage_Buffer source;
vImage_Buffer destination;
vImage_Error err = vImageBuffer_Init(&source, patchSide, patchSide, 8 * sizeof(Pixel_8), kvImageNoFlags);
err = vImageBuffer_Init(&destination, patchSide, patchSide, 8 * sizeof(Pixel_8), kvImageNoFlags);并将数据从sourceArea.data复制到source.data。请记住,source.rowBytes不太可能等同于source.width。
您还应该创建一个临时缓冲区,以便vImageAffineWarp_Planar8可以在每次迭代中重用它,而不是为每个迭代分配它,因为您将NULL作为第三个参数传递给它。要确定临时缓冲区的大小,您可以像在操作期间一样调用函数,但使用标志kvImageGetTempBufferSize,因为不同的参数/标志可能需要不同的缓冲区大小(参见@constant kvImageGetTempBufferSize in vImage_Types.h):
size_t tempBufferSize = vImageAffineWarp_Planar8(&source, &destination, NULL, &transform, 0, kvImageBackgroundColorFill | kvImageGetTempBufferSize);然后将分配临时缓冲区:
void *tempBuffer = malloc(tempBufferSize);最后,在您的循环中,每次都要使用tempBuf:
if (vImageAffineWarp_Planar8(&source, &destination, &tempBuffer, &transform, 0, kvImageBackgroundColorFill) != kvImageNoError)
{
NSLog(@"Error in warping!");
}因此,要重新分配,源、目的地和tempBuf都是在循环之前使用vImageBuffer_Init预先分配的,其中tempBuf的所需大小是通过调用循环中的vImageAffineWarp_Planar8来确定的,但需要使用附加标志kvImageGetTempBufferSize。希望这能加快你的速度!
如果您的算法支持它,最后一件事可能是在更大的块或图像条纹上工作(参见Tiling / Strip Mining and Multithreading节,vImage.h)。
https://stackoverflow.com/questions/25337267
复制相似问题