对于图像处理,我有一个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概念表达这个?
答案 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
。