将pragma omp与SSE代码并行混合:如何重置FPU?

时间:2013-06-06 13:34:36

标签: c sse openmp

对于图像处理,我有一个openmp-parallized循环遍历图像的每一行。在循环内部我使用的是SSE内在函数:

#pragma omp parallel for
for( int y=0; y<=img->height; y++ ) 
{
    [SSE Code]
}

从SSE切换到FPU代码时,我需要使用_mm_empty。我的理解是,openmp使用的每个 cpu都需要执行_mm_empty。

我目前的代码显然是错误的:

#pragma omp parallel for
for( int y=0; y<=img->height; y++ ) 
{
    [SSE Code]
}

_mm_empty();

只有一个CPU会重新初始化它。

到目前为止,我提出的最佳解决方案是性能损失:

#pragma omp parallel for
for( int y=0; y<=img->height; y++ ) 
{
    [SSE Code]
    _mm_empty();
}

这将为每个循环迭代调用_mm_empty。我期望OpenMP创建一个线程池,其线程数与可用的CPU数一样多,并在它们之间划分工作。例如,具有720行和4个CPU的图像,这将最终执行720次_mm_empty,而不是所需的4次。

OpenMP中是否有任何用于定义清理代码的概念,由每个线程执行?像

这样的东西
#pragma omp parallel for on thread exit( _mm_empty(); )
for( int y=0; y<=img->height; y++ ) 
{
    [SSE Code]
}

或者有没有办法用其他omp概念表达这个?

1 个答案:

答案 0 :(得分:2)

如果只是在每个线程中执行一条指令,那么标准的omp parallel pragma就应该这样做:

#pragma omp parallel for
for( int y=0; y<=img->height; y++ ) 
{
    [SSE Code]
}

#pragma omp parallel
_mm_empty();

或组合在一起

#pragma omp parallel
{
    #pragma omp for
    for( int y=0; y<=img->height; y++ ) 
    {
        [SSE Code]
    }
    #pragma omp barrier    //maybe, maybe not?
    _mm_empty();
}

但是您遇到的实际问题是,您无法确定这实际上是在前一个循环使用的每个核心上执行_mm_empty。您只能保证在其循环之后在每个线程中调用它(并且在所有线程完成其循环后使用屏障),但是OpenMP运行时(或OS)可以自由地在任何需要的地方和每当重新调度发生时调度线程。但是一个合理的运行时/操作系统应该确实将线程分配给特定的内核并保留在那里,也许你甚至可以通过一些OpenMP或OS函数来调整它。

但你知道吗,你可能根本不需要这种_mm_empty的疯狂。请注意,仅在使用 MMX 指令时才需要_mm_empty,这些指令是 SSE 的前身(仅使用64位而不是128位)并使用与 x87 FPU相同的寄存器。但是 SSE 带来了自己的一组寄存器以及它自己的状态和控制标志。因此 SSE 不会以任何方式干扰“经典”FPU,并且不需要任何同步。因此,如果它实际上只是您正在使用的 SSE 操作,而不是 MMX (即您只使用__m128(i)类型而不使用__m64 }类型),然后忘掉_mm_empty

相关问题