首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >vImage具有与普通循环dispatch_apply相同的性能。

vImage具有与普通循环dispatch_apply相同的性能。
EN

Stack Overflow用户
提问于 2014-08-16 05:36:11
回答 3查看 539关注 0票数 2

这段代码在嵌套循环中运行9600次,每次运行的时间都不到30 is,并且必须在iPhone4S上运行:

代码语言:javascript
复制
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点。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-08-16 18:42:18

10x10是一个非常小的图像。您可以轻松地将大部分时间花在开销/ malloc上。仪器的时间跟踪应该有助于确定时间的去向。

4s上的矢量ALU也是5或5s宽度的一半,因此不能提供比标量更大的胜利。

票数 3
EN

Stack Overflow用户

发布于 2014-08-16 22:06:46

如果能重用缓冲区,可见效果会更快。因此,如果可能的话,在循环之外声明和分配缓冲区(或相关数据)。

代码语言:javascript
复制
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
}
票数 1
EN

Stack Overflow用户

发布于 2015-04-01 11:44:01

在不对代码进行太多更改的情况下,您可能需要进行两项更改来提高性能:使用vImage框架分配源/目标缓冲区和创建临时缓冲区以便在循环中重用。第三个改变可能是改变你的瓷砖大小(见这个答案的结尾)。

vImage/ your框架的文档建议使用vImageBuffer_Init (参见vImage_Utilities.h)初始化缓冲区,以确保实际的缓冲区是

大小和对齐,以获得最佳性能

而不是自己分配内存:

代码语言:javascript
复制
vImage_Buffer buffer;
vImage_Error err = vImageBuffer_Init(&buffer, height, width, 8 * sizeof(pixel), kvImageNoFlags);

在您的例子中,pixel将是Pixel_8,因为您使用的是*_Planar8函数。注意,当您完成buffer.data时,仍然需要释放它。

因此,您应该在循环之外初始化源和目标:

代码语言:javascript
复制
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):

代码语言:javascript
复制
size_t tempBufferSize = vImageAffineWarp_Planar8(&source, &destination, NULL, &transform, 0, kvImageBackgroundColorFill | kvImageGetTempBufferSize);

然后将分配临时缓冲区:

代码语言:javascript
复制
void *tempBuffer = malloc(tempBufferSize);

最后,在您的循环中,每次都要使用tempBuf

代码语言:javascript
复制
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)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25337267

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档