我很想知道/LARGEADDRESSAWARE
交换机是如何工作的,并且找不到太多关于实现细节的信息。
任何人都可以描述使用开关时发生的情况及其后果(除了允许进程访问更多内存)吗?
我很想知道/LARGEADDRESSAWARE
交换机是如何工作的,并且找不到太多关于实现细节的信息。
任何人都可以描述使用开关时发生的情况及其后果(除了允许进程访问更多内存)吗?
从历史上看,32 位 Windows 系统会有一个虚拟内存布局,其中只有低 2 GB 的进程地址空间会被应用程序使用;上面的 2 GB 将保留给内核。这是记录在案的行为。更改记录的行为并不酷,除非它明确选择加入。这/LARGEADDRESSAWARE
就是为了。它在可执行文件头中触发一个标志,告诉系统程序不会介意使用超过 2GB 边界的地址。使用该标志,系统可以从低 3 GB 分配地址,高 1 GB 用于内核。
您将如何对应用程序进行编码以使这是一个重大变化,这完全是另一个问题。也许有些人会将地址转换为已签名的整数并进行比较;如果地址设置了第 31 位,那将会中断。
编辑:交换机本身对性能没有影响。但是,如果应用程序经常遇到超过 2 GB 的内存负载,您可以通过更积极的缓存获得一些性能。如果没有 3GB 开关,应用程序不能消耗超过 2GB 的虚拟内存;带开关,最多三个。
我在Venice、Sphere和100k数据集上使用SLAM++库运行了一个简单的基准测试:
Dataset | Time x86 | Time x86 /LARGEADDRESSAWARE | Time x64
Venice | bad_alloc | 4276.524971 | 300.315826 sec
Sphere | 2.946498 | 3.605073 | 1.727466 sec
100k | 46.402400 | 50.196711 | 32.774384 sec
所有时间都以秒为单位。你有它 - 性能损失可能是巨大的。这主要是在做 BLAS 操作,有时使用 SSE 加速,整个事情都受内存限制。请注意, x86 中Venice的峰值内存使用量略高于 3.5 GB(我相信在 x64 系统中最高可达 4 GB),在 x64 中则略低于 4.3 GB。其他数据集使用的内存要少得多,远低于 2 GB。
/LARGEADDRESSAWARE
在Venice上的 x86 的情况下,操作系统似乎希望将大部分 >2 GB 保留在分页文件中,尽管在访问数据时内存使用量跃升至 >3 GB - 因此额外成本可能源于激进分页. 此外,x64 中的算术运算比 x86 有一些优势(程序可以使用额外的寄存器等),这可能是普通 x86 在小型数据集上比 x64 慢的原因。
这是在具有 2 个AMD Opteron 2356 SE和 16 GB 的 667 MHz DDR2、运行 Windows Server 2003 x64 的机器上测量的。
在 Windows 7、Intel Core i7-2620M、8 GB 1333 MHz DDR3 机器上:
Dataset | Time x86 | Time x86 /LARGEADDRESSAWARE | Time x64
Venice | bad_alloc | 203.139716 | 115.641463 sec
Sphere | 1.714962 | 1.814261 | 0.870865 sec
100k | 18.040907 | 18.091992 | 13.660002 sec
这具有非常相似的行为,x64 比 x86 快,并且/LARGEADDRESSAWARE
速度较慢(尽管没有前一种情况那么慢 - 它可能取决于 CPU 或操作系统)。
/LARGEADDRESSAWARE
不会影响性能,因为它不影响代码生成。
未设置此标志的程序只能获得 < 2^31 的虚拟内存地址。具有此标志集的程序可能会获得 > 2^31 的虚拟地址。
这很重要,因为在依赖有符号整数数学的程序中可能存在细微的错误。
例如将指针转换为 int:
void* p0 = ...; // from somewhere
void* p1 = ...; // from somewhere else
assert( p1 > p0 );
int diff = (int)p1 - (int)p0;
这将在地址 > 2 GB 的情况下中断。因此,保守起见,操作系统确实会处理未设置此标志的程序,因为它“在遇到大于 2 GB 的地址时可能会做坏事”。
另一方面,在 x86 系统上,设置/3GB
标志会减少内核可用的虚拟内存量,这可能会影响其性能。