对于图像处理,我有一个贯穿图像每一行的 openmp 并行循环。在循环内部我使用 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 会重新初始化其 FPU。
到目前为止我想出的最佳解决方案会带来性能损失:
#pragma omp parallel for
for( int y=0; y<=img->height; y++ )
{
[SSE Code]
_mm_empty();
}
这将为每次循环迭代调用 _mm_empty。我期望 OpenMP 创建一个线程池,其中的线程数量与可用的 CPU 数量差不多,并在它们之间分配工作。例如,具有 720 行和 4 个 CPU 的镜像,最终将导致 _mm_empty 被执行 720 次,而不是所需的 4 次。
OpenMP 中是否有用于定义由每个线程执行的清理代码的概念?类似的东西
#pragma omp parallel for on thread exit( _mm_empty(); )
for( int y=0; y<=img->height; y++ )
{
[SSE Code]
}
或者有没有办法用其他 omp 概念来表达这一点?
最佳答案
如果只是在每个线程中执行一条指令,那么标准的 omp parallel
编译指示应该做到这一点:
#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 运行时(或操作系统)可以在任何需要的地方以及每当发生重新调度时自由地调度线程。但是一个明智的运行时/操作系统确实应该关心线程被分配给特定的核心并留在那里,也许您甚至可以通过某些 OpenMP 或操作系统功能来调整它。
但你知道吗,你可能根本不需要这种_mm_empty
疯狂。请记住,仅在使用 MMX 指令时才需要 _mm_empty
,该指令是 SSE 的前身(只有 64 位,而不是 128 位) )并使用与 x87 FPU 相同的寄存器。但是SSE带来了自己的一组寄存器以及自己的状态和控制标志。因此,SSE 不会以任何方式干扰“经典”FPU,并且不需要任何同步。因此,如果您实际上仅使用 SSE 操作,而不是 MMX(即您只使用过 __m128(i)
类型,并且永远不要使用 __m64
类型),然后就忘记 _mm_empty
吧。
关于c - 将 pragma omp parallel for 与 SSE 代码 : How to reset FPU? 混合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16963536/