1

读取共享变量的线程必须首先调用flush,然后写入共享变量的线程必须调用 OpenMP flush,以使共享变量在主内存和缓存中保持同步。函数如何flush知道要冲向哪个方向?它需要知道两个变量(主内存或缓存)中的哪一个更新。我假设,但我不确定,操作系统或 CPU 会以某种方式处理这个问题。有人知道吗?

4

2 回答 2

1

flush不是函数 - 它是 OpenMP编译器指令。它影响编译器生成可执行代码的方式,并指示它同步刷新集中所有优化变量(存储在 CPU 寄存器或其他显式可编程缓存/线程本地内存中)的值。这类似于volatilestorage 修饰符对代码生成的影响,但具有更有限的点局部效果。

它是如何工作的?在解析源代码时,编译器会分析语句流和受这些语句影响的数据(变量)。因此,编译器从代码构建执行图和数据依赖图。它确切地知道每个变量的值在哪里以及如何被使用,以及哪个代码块的执行会影响哪些变量。然后编译器尝试通过简化图形来优化代码,并通过使用 CPU 寄存器存储中间值或使用另一个更快的线程可寻址本地内存来减少昂贵的内存操作的数量。这flush指令在执行图中添加了特殊点,编译器必须显式地将线程的内存视图(寄存器变量和本地内存变量)与全局共享内存同步。由于编译器首先构建了依赖关系图,它确切地知道刷新集中的哪些变量被修改,因此必须写入共享内存;刷新集中的所有其他变量都必须从共享内存中读取。

因此,您的问题的答案是,通常是编译器处理flush指令,而不是操作系统,尽管编译器可能会调用操作系统来实际实现刷新,例如在具有显式可编程缓存/本地存储器的系统上。但也应该注意,OpenMP 是一种抽象标准,可以在许多不同的硬件平台上实现,并且其中一些平台提供了某些硬件,可以帮助更有效地实现 OpenMP 抽象(例如 IBM Blue Gene 中的 CPU ASIC/ Q 提供了许多这样的功能)。

于 2013-02-15T12:33:01.290 回答
-1

您不需要调用 flush 来保持共享变量同步。硬件(CPU)确实会跟踪缓存的内存,如果存在冲突的访问,它们会减慢您的程序,因为缓存将被 CPU 刷新。

我理解 flush 指令更像是一个条件屏障。必须至少有两个线程遇到包含相同变量的刷新才能生效。当具有共同变量 a 的两个线程满足该指令时,如果他们修改了它,他们会将修改写回内存(而不是将其保存在局部变量或寄存器中),然后我想有一个障碍让两个线程在继续之前到达该点。如果变量 a 在刷新后使用,则从内存中重新读取。

于 2013-02-15T11:01:51.170 回答