加速图像处理的神器: Intel ISPC编译器 (五) 迁移图像旋转算法 - ISPC单精度 从单核到多核 及最终性能提升结果

本文主要是介绍加速图像处理的神器: Intel ISPC编译器 (五) 迁移图像旋转算法 - ISPC单精度 从单核到多核 及最终性能提升结果,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

现在CPU的核心数越来越多,即使现在的移动平台也是动辄4核起。前面的代码都是用单线程来运行的,所以只用到了CPU的一个核心。接下来尝试一下使用ISPC多任务机制来利用CPU的多核加速。

 

ISPC代码从单核到多核的优化

在ISPC的开发手册里,最简单的多任务机制用到了2个关键字 launch和task

  • 在一个函数前面加关键字task,标识这个函数是任务函数,可以在其他代码里通过launch语句来启动。任务函数可以被同时启动多次,在函数里有个内建的变量taskIndex, 标识着当前任务是第几个任务。
task void foo_task()
{print("taskIndex = %\n", taskIndex);
}
  • launch用来启动任务,launch后面的数组[100]表示同时启动100个foo_task任务
launch[100] foo_task();
  • ISPC编译器默认不提供多任务管理库,也就是说对应launch任务的底层函数需要自己来实现,具体的说明可以参考开发手册的“Task Parallelism: Runtime Requirements”部分。好在ISPC的例程里自带了一套示例代码tasksys.cpp, 前面在cmake的配置文件里设置USE_COMMON_SETTINGS,项目就会自动编译链接这个tasksys.cpp。

 

 接下来把image_rotate_float_ispc()改成多任务版,先把输入图像分成多个小块,每个任务处理32像素高度的图像
块。

对应代码

#define M_PI_F 3.1415926535ftask void image_rotate_float_ispc_task(uniform const uint8 srcImg[], uniform uint8 dstImg[], uniform float center_x,uniform float center_y, uniform int iWidth, uniform int iHeight, uniform int span, uniform float skewDegree)
{//计算当前任务需要处理的图像块的起始y坐标和结束y坐标uniform int ystart = taskIndex * span;uniform int yend = min((taskIndex+1) * span, (unsigned int)iHeight);uniform float angle = (float)RotateDegree*M_PI_F / 180.0;uniform float alpha = cos(angle);uniform float beta = sin(angle);uniform float m[6];m[0] = alpha;m[1] = -beta;m[2] = (1.0 - alpha) * (float)center_x + beta * (float)center_y ;m[3] = beta;m[4] = alpha;m[5] = (1.0 - alpha) * (float)center_y - beta * (float)center_x;foreach (row = ystart ... yend, col = 0 ... iWidth)  {float x, y;int leftX, rightX, topY, bottomY;float w00, w01, w10, w11;float fxy;x = m[0] * (float)col + m[1] * (float)row + m[2];y = m[3] * (float)col + m[4] * (float)row + m[5];leftX = floor(x);topY = floor(y);rightX = leftX + 1.0;bottomY = topY + 1.0;w11 = abs(x - leftX)*abs(y - topY);w01 = abs(1.0 - (x - leftX))*abs(y - topY);w10 = abs(x - leftX)*abs(1 - (y - topY));w00 = abs(1.0 - (x - leftX))*abs(1.0 - (y - topY));if ((int)leftX >= 0 && (int)rightX < Width && (int)topY >= 0 && (int)bottomY < Height) {fxy = (float)srcImg[topY*Width+ leftX]*w00 + (float)srcImg[bottomY*Width+ leftX]*w01 +(float)srcImg[topY*Width+ rightX]*w10 + (float)srcImg[bottomY*Width+ rightX]*w11;fxy = round(fxy);if (fxy < 0)fxy = 0;if (fxy > 255)fxy = 255;dstImg[row*Width+ col] = (uint8)(fxy);}elsedstImg[row*Width + col] = 0;};
};export void myWarpAffine_float_ispc_mt(uniform const uint8 srcImg[], uniform uint8 dstImg[], uniform float center_x,uniform float center_y, uniform int iWidth, uniform int iHeight, uniform float skewDegree)
{//任务分块,定义每个任务处理32像素高的图像块uniform int span = 32;//启动任务launch[iHeight/span] image_rotate_float_ispc_task(srcImg, dstImg, center_x, center_y, iWidth, iHeight, span, skewDegree);
};

 

运行一下多任务版本,我这个4核8线程的笔记本上耗时: 230ms

ISPC多核对单核算法的效率对比为

781ms/230ms=3.40X

也基本接近了4核4倍的理论值

 

最后的收官优化

在最后阅读ISPC开发手册的时候,发现了一个clamp函数

The clamp() functions clamp the provided value to the given range. (Their implementations are based on min() and max() and are thus quite efficient.)float clamp(float v, float low, float high)

这不就是做我的代码里的把最终算出的像素值卡到[0,255]之间的功能么,赶快替换一下

				fxy = round(fxy);
#if 0if (fxy < 0)fxy = 0;if (fxy > 255)fxy = 255;
#elsefxy = clamp(fxy,0,255);
#endif

最后多核的运行时间: 211ms  又快了一点 :)

 

最终的性能提升总结

代码优化到这里,已经利用了SIMD和多核的硬件优势,大的优化可能基本已经没有了。如果要进一步的优化,就需要从内存和缓存的读取写入的利用率来重新调整代码架构了。这就属于终极优化部分了,对于我这个测试程序就没有意义了。

 

现在对比一下原始C代码和ISPC多核版本的性能提升

4294ms/211ms = 20.35X

 

对应的是并不多的改动时间,回报是巨大的,ISPC真乃神器 强烈推荐:)

 

最后放上ISPC的几个链接

ISPC的主页   这里是总入口,可以找到各种发行包,开发文档以及性能测试等各类信息

ISPC的Github ISPC编译器是完全开源的,有兴趣开发者的可以加上对自家硬件的支持

 

这篇关于加速图像处理的神器: Intel ISPC编译器 (五) 迁移图像旋转算法 - ISPC单精度 从单核到多核 及最终性能提升结果的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/300997

相关文章

Python并行处理实战之如何使用ProcessPoolExecutor加速计算

《Python并行处理实战之如何使用ProcessPoolExecutor加速计算》Python提供了多种并行处理的方式,其中concurrent.futures模块的ProcessPoolExecu... 目录简介完整代码示例代码解释1. 导入必要的模块2. 定义处理函数3. 主函数4. 生成数字列表5.

基于Python+PyQt5打造一个跨平台Emoji表情管理神器

《基于Python+PyQt5打造一个跨平台Emoji表情管理神器》在当今数字化社交时代,Emoji已成为全球通用的视觉语言,本文主要为大家详细介绍了如何使用Python和PyQt5开发一个功能全面的... 目录概述功能特性1. 全量Emoji集合2. 智能搜索系统3. 高效交互设计4. 现代化UI展示效果

Python中OpenCV与Matplotlib的图像操作入门指南

《Python中OpenCV与Matplotlib的图像操作入门指南》:本文主要介绍Python中OpenCV与Matplotlib的图像操作指南,本文通过实例代码给大家介绍的非常详细,对大家的学... 目录一、环境准备二、图像的基本操作1. 图像读取、显示与保存 使用OpenCV操作2. 像素级操作3.

C/C++的OpenCV 进行图像梯度提取的几种实现

《C/C++的OpenCV进行图像梯度提取的几种实现》本文主要介绍了C/C++的OpenCV进行图像梯度提取的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录预www.chinasem.cn备知识1. 图像加载与预处理2. Sobel 算子计算 X 和 Y

JVisualVM之Java性能监控与调优利器详解

《JVisualVM之Java性能监控与调优利器详解》本文将详细介绍JVisualVM的使用方法,并结合实际案例展示如何利用它进行性能调优,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全... 目录1. JVisualVM简介2. JVisualVM的安装与启动2.1 启动JVisualVM2

c/c++的opencv图像金字塔缩放实现

《c/c++的opencv图像金字塔缩放实现》本文主要介绍了c/c++的opencv图像金字塔缩放实现,通过对原始图像进行连续的下采样或上采样操作,生成一系列不同分辨率的图像,具有一定的参考价值,感兴... 目录图像金字塔简介图像下采样 (cv::pyrDown)图像上采样 (cv::pyrUp)C++ O

Java使用MethodHandle来替代反射,提高性能问题

《Java使用MethodHandle来替代反射,提高性能问题》:本文主要介绍Java使用MethodHandle来替代反射,提高性能问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录一、认识MethodHandle1、简介2、使用方式3、与反射的区别二、示例1、基本使用2、(重要)

Python+PyQt5实现MySQL数据库备份神器

《Python+PyQt5实现MySQL数据库备份神器》在数据库管理工作中,定期备份是确保数据安全的重要措施,本文将介绍如何使用Python+PyQt5开发一个高颜值,多功能的MySQL数据库备份工具... 目录概述功能特性核心功能矩阵特色功能界面展示主界面设计动态效果演示使用教程环境准备操作流程代码深度解

使用animation.css库快速实现CSS3旋转动画效果

《使用animation.css库快速实现CSS3旋转动画效果》随着Web技术的不断发展,动画效果已经成为了网页设计中不可或缺的一部分,本文将深入探讨animation.css的工作原理,如何使用以及... 目录1. css3动画技术简介2. animation.css库介绍2.1 animation.cs

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.