【问题标题】:OpenMP: how to flush pointer target?OpenMP:如何刷新指针目标?
【发布时间】:2011-06-16 19:53:32
【问题描述】:

我刚刚注意到以下代码无法在 OpenMP(GCC 4.5.1 下)中编译:

struct job {
    unsigned busy_children;
};

job* j = allocateJob(…);
// …

#pragma omp flush(j->busy_children)

编译器抱怨要刷新的参数列表中的 ->,根据 OpenMP 规范,这是正确的:flush 期望参数列表为“id-expression”列表,这基本上意味着仅(限定)允许使用 ID,不允许使用表达式。

此外,规范中提到了flush 和指针:

如果列表中存在指针,则刷新指针本身,而不是指针所指的内存块。

当然。但是,由于 OpenMP 也不允许我取消引用指针,因此我基本上无法刷新指针(指针目标)。

– 那么引用呢?规范没有提到它们,但我不确定以下是否符合要求,并且实际上会刷新指针。

unsigned& busy_children = j->busy_children;
#pragma omp flush(busy_children)

这能保证有效吗?

如果没有,如何刷新指针?

【问题讨论】:

  • MSDN 说“flush 指令中指定的变量不能有引用类型”。所以不能保证在所有平台上工作。不了解 GCC。
  • @Kyrill:啊,他妈的。顺便说一句,OpenMP 规范确实没有提到这一点,3.0 和 2.5 都没有。并且 MSDN 中的章节编号不同。

标签: c++ pointers reference openmp flush


【解决方案1】:

flush 指令让 OpenMP ARB 头疼已久。如此之多,以至于有人谈论要完全删除它——尽管这会产生其他问题。使用flush(list) 非常难以正确,即使是OpenMP 专家也很难正确。它的问题在于它的定义方式可以由编译器在您的代码中移动。这意味着你应该远离使用flush(list)。

至于您关于能否刷新指针的问题,只有一种方法可以做到这一点,那就是使用刷新(没有列表)。这将刷新您的整个线程环境,因此编译器无法移动。看起来“笨手笨脚”,但编译器实际上非常擅长在没有列表的情况下使用 flush 时刷新必要的内容。

【讨论】:

  • 嗯,这有点烦人。感谢您分享这一见解。然后我会吞下苦果,然后刷新整个环境……我确实需要刷新那个引用。
【解决方案2】:

OpenMP 规范没有直接说明变量的类型,但 MSDN 说“在刷新指令中指定的变量不能有引用类型”。这让我认为这不能保证有效。带有空变量列表的 flush 指令应该刷新所有内存,因此您可以安全地使用它。

【讨论】:

    【解决方案3】:

    您不能刷新取消引用的指针的原因是因为只有硬件寄存器中的值才需要刷新。在 OpenMP 下,永远不需要刷新不在硬件寄存器中的东西(例如,在缓存或内存中),因为 OpenMP 假设有一个一致的缓存内存,它保证所有线程在相同地址时总是看到相同的值。取消引用。硬件协议保证缓存一致性,使多个本地缓存表现得像一个共享的全局缓存。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-26
      相关资源
      最近更新 更多