- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
首先,在有人提示之前,我意识到在理论上完美的C++代码的角度来看,内存模型是一个我不应该依赖的实现细节。但是,我更喜欢表现而不是纪律。
场景是这样的:我有一个地址空间区域,我告诉操作系统用我选择的文件来支持它——也就是说,该文件是内存映射的。如果我对 VMM 通常如何工作的理解是正确的,那么操作系统可能会很懒惰地将页面加载到我的映射中,并且可能只会在页面实际被触及时才这样做。
通常我可以忽略这个细节,但在这种特殊情况下,我将映射数据发送到工作线程池中。如果我只是天真地向工作线程传递一个指向该缓冲区的指针,那么很有可能工作线程本身会在第一次触摸页面时遇到页面错误,这将导致工作线程阻塞,直到页面被物理访问由 VMM 加载。
工作池的设计使得它的线程在 I/O 上阻塞是非常糟糕的,而发送作业的线程可以容忍被阻塞。因此,我想让我的发送者线程首先接触映射的页面,这样页面错误就会阻止它。
(我知道没有保证先触摸页面会停止工作线程中的后续页面错误,但程序仍然会在大多数时间处于最佳状态并始终纠正.)
在 x86 汇编语言中,这将是微不足道的:
; get the page's address in ebx
mov al, Byte Ptr [ebx]
不幸的是,在 C 或 C++ 中就没那么简单了。天真的实现很简单:
char *pPage = ...;
char Dummy = *pPage;
但是,这可能行不通,因为任何有自尊心的优化器都会意识到代码什么都不做而只是忽略它。
我们可以使用内联汇编,但这可能会严重削弱优化器。我们可以调用一个汇编语言函数来完成它,但是我们有(公认的小)不必要的函数调用开销。
我们可以改为使 Dummy
成为一个外部可见的变量,这会起作用,因为编译器不能假定赋值是无意义的。但是,这会导致对包含 Dummy
的 CPU 缓存行的争用,从而严重降低多核系统的性能。 (更不用说,我们浪费了缓存行和访问权限。)
我也想到了这样做:
char volatile *pPage = ...;
char Dummy = *pPage;
我知道 volatile
关键字有两个保证:
编译器不会重新排序访问;和
编译器不会假定连续读取之间的值相同。
但是,这似乎并不能保证编译器即使不需要它也会读取该值。
有什么想法吗?
最佳答案
volatile
根据定义保证执行内存访问,因此一个简单的解决方案正是您所建议的:
volatile char *prefetch_me = ...;
(void)*prefetch_me;
但是,如果您想以(可能)更有效的方式访问多个页面(并且您在 *ix 系统上运行),请查看 madvise()
,特别是 MADV_WILLNEED
和/或 MADV_SEQUENTIAL
。从手册页:
MADV_WILLNEED
- 期望在不久的将来访问。 (因此,提前阅读几页可能是个好主意。)MADV_SEQUENTIAL
- 期望页面引用按顺序排列。 (因此,给定范围内的页面可以被积极地提前读取,并可能在访问后很快被释放。)关于c++ - 如何故意触摸内存页?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18929011/
首先是我的对象: public class Group { private final ObservableList sourceList; private final Obser
我有一个 Circle 类和一个 Rectangle 类。我现在想创建一个类 FunnyObject,每个类都由一个圆和两个矩形组成。 如果我这样做: class FunnyObject:public
我正在阅读一篇博文 here关于用 node.js 创建一个刮板并遇到了一些有趣的 javascript,我无法完全理解。这正是我想在我的脚本中使用的东西,但作为一个新手,我不想在不知道它们首先做什么
我不明白为什么在成功之后我为什么看不到脚本中的错误(我用谷歌搜索,它只是给出了关于jquery get脚本成功/错误时错误处理的很多答案)。 如果我使用“any” js脚本执行此操作 $.getScr
我目前正在为我公司正在开发的设备( radio 编码器)开发单元测试。 可以通过 SNMP(仅限 v1)访问各种统计信息,其中您可以获得由于各种原因丢弃的 UDP 数据报的数量。 我希望能够发送一个包
这是一个令人费解的问题。我运行良好的 ASP.NET 3.5 应用程序突然开始出现超时错误... System.Data.SqlClient.SqlException:超时已过。操作完成前超时时间已过
我正在尝试掌握 C++ 内存管理的窍门,并尝试使用无限循环的新语句故意使我的程序崩溃。据我了解,这只会在内存堆上保留越来越多的空间。但是我的程序不会崩溃。在 Windows 任务管理器中监控它,它将使
我是一名优秀的程序员,十分优秀!