c - 将 pragma omp parallel for 与 SSE 代码 : How to reset FPU? 混合

标签 c sse openmp

对于图像处理,我有一个贯穿图像每一行的 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/

相关文章:

c++ - 将JNI代码移植到java并理解jdouble * 用法

c - 如何使用 libssl 对文件进行签名?

c++ - clang 模板化使用 __attribute__((vector_size(N)))

x86 - 如何使用 SSE 计算某个范围内的字节数?

linux - numactl 和 move_pages 不匹配

c++ - 如何在 C 中设计样式?

c - Linux 设备驱动程序中的静态函数?

c++ - 为什么在这种特殊情况下数据类型会影响性能?

c++ - 为什么thread_local不能应用于非静态数据成员以及如何实现线程局部非静态数据成员?

fortran - Fortran+openMP 的简单分析?