2008年4月7日星期一

介绍英特尔的优化库IPP(下)

有了(上)的基础,可以谈一下深一步的内容了。使用IPP函数,程序或者使用动态库连接,或者是静态库连接。

使用动态库的场合,需要在IPP安装目录stublib下的库,如ippi.lib。这时执行程序本身不大,但需要IPP的DLL,它们一般是在IPP安装目录bin下,名字为ippi.dll等,还有和平台相关的DLL,稍后会详细解释。

使用静态库的情况,要使用IPP安装目录lib下的库,如ippimerged.lib。这样生成的程序比较大,因为含有所有执行平台的模块,好处是不再需要IPP的DLL了。

使用动态静态库的问题,是C语言的常识,这里不多加讨论。需要解释一下IPP的工作原理。

[更多:]


看IPP安装目录bin下有个文件叫libguide40.dll,这是判断计算机CPU类型的,从而决定调用哪个对应平台的DLL。比如,bin下的ippi.dll其实只是个接口,真正的功能是靠以下4个DLL之一实现的:ippipx.dll,ippia6.dll,ippiw7.dll,ippit7.dll。(最新版5.1的文件命名方式略有变化,版本号也被使用,成了ippi-5.1.dll)

以上的px,a6,w7,t7实际上指定了应用平台。据英特尔称,px用于一般的芯片,a6用于奔腾3的芯片,w7用于普通的奔腾4芯片,而t7用于新的Prescott核心的奔4。对于其对手AMD的芯片,则一律认定是普通的芯片px,不给与特殊优化。

但AMD芯片的用户就只能用普通IPP功能了吗?同样的问题在一些嵌入式系统的用户中也有,因为这些系统的芯片也会声称和英特尔芯片兼容。再仔细考察IPP的原理,可以发现,还是有办法强迫IPP对非英特尔芯片进行优化的。

其实所有IPP函数都是裸函数,全部由汇编写成,C语言的函数定义不过是提供了接口而已。这样对用户的好处是用同一代码可以得到不同平台的优化。以上的px/a6/w7/t7实际上和英特尔的指令集合有关系:

t7对应了SSE3。
w7对应了SSE2。
a6对应了SSE。
px就是普通的MMX。

所以根据你手头的CPU是否对应以上的指令集,可以通过这样的方法来使用IPP的优化。要注意的是程序调用必须以__stdcall 的方式,也就是编译器用/Gz为选项。以下的代码可以加入在(上)中的例子:

#include
#ifdef IPPAPI
#undef IPPAPI
#endif

#ifndef IppiAxis
typedef enum {
ippAxsHorizontal,
ippAxsVertical,
ippAxsBoth
} IppiAxis;
#endif

extern "C"
{
#define IPPAPI(type,name,arg) extern type px_##name arg;
static type (*d##name) arg = px_##name;
__declspec(naked) type name arg { __asm {jmp d##name } }
IPPAPI(void, ippiFree, (void* ptr))
IPPAPI(Ipp8u*, ippiMalloc_8u_C1, (int widthPixels, int heightPixels, int* pStepBytes))
IPPAPI(IppStatus, ippiMirror_8u_C3IR, (Ipp8u* pSrcDst, int srcDstStep, IppiSize roiSize, IppiAxis flip))
}


这里需要对原来的ippMalloc/ippFree的两行换成:
data = (Ipp8u *)ippiMalloc_8u_C1((int)szFile, 1, &lineStep);

ippiFree(data);
可以根据需要将代码中的px换成a6/w7/t7等。

因为有这样方便的机制,才使得我们可以在源代码不改的情况下也能获得Intel新平台的优化。

1 条评论:

WANGHU 说...

评论源自: 崴跛司机
友情bump一哈
06-04-28 @ 23:28

评论源自: WANGHU
偶这些咚咚,更多的是写给自己看。岁数大了,记性开始不好。 :(

司机有空倒是应该把自己的院子整理一哈。
06-04-29 @ 06:34