2012-10-23 162 views
0

我想通过结合IPP和TBB在我的图像调整大小算法中获得进一步的改进。我可以完成这个任务的两种方法是:结合英特尔IPP和TBB

  1. 使用IPP没有TBB
  2. 使用IPP与TBB一个parallel_for时循环

我的问题是,我已经编写的应用程序中,我得到正确的结果。但令人惊讶的是,当他们合并时,我的计算时间更长。为了避免混乱,我只在这里粘贴了部分代码。但是如果需要,我可以提供整个代码。对于当我只用IPP第一种情况下,该代码是这样的:(该算法的基础是从用于图像大小调整英特尔TBB示例代码借用)

ippiResizeSqrPixel_8u_C1R(src, srcSize, srcStep, srcRoi, dst, dstStep, dstRoi, 
m_nzoom_x,m_nzoom_y,0, 0, interpolation, pBufferWhole); 

和parallel_for时循环如下所示:

parallel_for(
    blocked_range<size_t>(0,CHUNK), 
    [=](const blocked_range<size_t> &r){ 
     for (size_t i= r.begin(); i!= r.end(); i++){ 
      ippiResizeSqrPixel_8u_C1R(src+((int)(i*srcWidth*srcHeight)), srcSize, 
srcStep, srcRoi, dst+((int)(i*dstWidth*dstHeight)), dstStep, dstRoi, 
m_nzoom_x,m_nzoom_y,0, 0, interpolation, pBuffer); 
     } 
    } 
); 

srcdst是指向源图像和目标图像的指针。当使用TBB时,图像被划分为CHUNKS部分,parallel_for循环遍历所有CHUNKS,并使用IPP函数独立调整每个CHUNK的大小。对dstHeight,srcHeight,和dstRoi的值进行修改以适应图像的分区,并且src+((int)(i*srcWidth*srcHeight))dst+((int)(i*dstWidth*dstHeight))将指向源和目标图像中每个分区的开始。

显然,IPP和TBB可以以这种方式结合 - 因为我得到了正确的结果 - 但令我感到困惑的是,与单独使用IPP时相比,当它们结合时,计算时间会恶化。任何关于可能是什么原因的想法,或者我如何解决这个问题?

谢谢!

+0

我假设图像尺寸太小而不能利用并行性。你测试了多大的输入/输出图像? – yohjp

+0

这是我最初的想法,但即使在我测试了比原尺寸大几倍的大尺寸图像后,我也没有看到任何改进。 – SMir

+0

您是否尝试分析此问题?你在哪个平台上。 – Rick

回答

0

原来,一些IPP功能使用自动多线程。对于这些功能,使用TBB无法获得改进。显然ippiResizeSqrPixel_8u_C1R(...)函数是其中的一个函数。当我禁用所有内核时,只有一个内核,两个版本都同样好。

0

在您的代码中,parallel_for中的每个并行任务由多个ippiResizeSqrPixel调用组成。 与仅调用一次的串行版本相比,这可能是无意义的开销,因为此函数可能包含准备阶段(例如,设置插值系数表),并且它通常设计为一次处理大内存块以提高运行时效率。 (但我不知道IPP实际上怎么做。)

我建议你以下并行结构:

parallel_for(
    // Range = src (or dst) height of image. 
    blocked_range<size_t>(0, height), 
    [=](const blocked_range<size_t> &r) { 
    // 'r' = vertical range of image to process in this task. 
    // You can calculate src/dst region from 'r' here, 
    // and call ippiResizeSqrPixel once per task. 
    ippiResizeSqrPixel_8u_C1R(...); 
    } 
); 
+0

我很难弄清楚代码中的不同之处。你能否完成你的循环体? – SMir

+0

其基本思想是:(1)通过调用一次IPP函数使并行执行的任务最小化;(2)纵向分割'parallel_for'的图像块并让TBB确定作为调用函数单元的块大小。 – yohjp