windows 如何在C++中通过编程获得CPU缓存行大小?

zysjyyx4  于 2023-02-13  发布在  Windows
关注(0)|答案(8)|浏览(284)

我想让我的程序读取它在C++中运行的CPU该高速缓存线大小。
我知道这不可能做到便携,所以我需要一个Linux和另一个Windows的解决方案(其他系统的解决方案可能对其他人有用,所以如果你知道的话,请发布它们)。
对于Linux,我可以读取/proc/cpuinfo的内容并解析以cache_alignment开头的行,也许有一个更好的方法涉及到调用API。
对于Windows,我根本不知道。

yi0zb3m4

yi0zb3m41#

在Win32上,GetLogicalProcessorInformation将给予一个包含CACHE_DESCRIPTORSYSTEM_LOGICAL_PROCESSOR_INFORMATION,其中包含您需要的信息。

cl25kdpy

cl25kdpy2#

在Linux上尝试proccpuinfo library,这是一个独立于体系结构的C API,用于阅读/proc/cpuinfo

vdgimpew

vdgimpew3#

对于x86,CPUID指令。快速的谷歌搜索会发现一些用于win32和c++的libraries。我也通过内联汇编程序使用过CPUID。
更多信息:

oyxsuwqo

oyxsuwqo4#

看起来至少SCO unix(http://uw714doc.sco.com/en/man/html.3C/sysconf.3C.html)有_SC_CACHE_LINE用于sysconf。也许其他平台也有类似的东西?

brqmpdu1

brqmpdu15#

在Windows上

#include <Windows.h>
#include <iostream>

using std::cout; using std::endl;

int main()
{
    SYSTEM_INFO systemInfo;
    GetSystemInfo(&systemInfo);
    cout << "Page Size Is: " << systemInfo.dwPageSize;
    getchar();
}

在Linux上

http://linux.die.net/man/2/getpagesize

9rbhqvlz

9rbhqvlz6#

下面是一些示例代码,供那些想知道如何在接受答案中使用该函数的人参考:

#include <new>
#include <iostream>
#include <Windows.h>

void ShowCacheSize()
{
    using CPUInfo = SYSTEM_LOGICAL_PROCESSOR_INFORMATION;
    DWORD len = 0;
    CPUInfo* buffer = nullptr;

    // Determine required length of a buffer
    if ((GetLogicalProcessorInformation(buffer, &len) == FALSE) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
    {
        // Allocate buffer of required size
        buffer = new (std::nothrow) CPUInfo[len]{ };

        if (buffer == nullptr)
        {
            std::cout << "Buffer allocation of " << len << " bytes failed" << std::endl;
        }
        else if (GetLogicalProcessorInformation(buffer, &len) != FALSE)
        {
            for (DWORD i = 0; i < len; ++i)
            {
                // This will be true for multiple returned caches, we need just one
                if (buffer[i].Relationship == RelationCache)
                {
                    std::cout << "Cache line size is: " << buffer[i].Cache.LineSize << " bytes" << std::endl;
                    break;
                }
            }
        }
        else
        {
            std::cout << "ERROR: " << GetLastError() << std::endl;
        }

        delete[] buffer;
    }
}
llew8vvj

llew8vvj7#

我认为您需要ntdll.dll中的NtQuerySystemInformation

nbewdwxp

nbewdwxp8#

如果您的实现支持,C17 std::hardware_destructive_interference_size会给予您一个上限(..._constructive_...是一个下限),考虑到像行对的硬件预取这样的东西。
但这些都是编译时常量,因此对于允许不同行大小的ISA,不可能在所有微体系结构上都是正确的。(例如,早期的x86 CPU(如Pentium III)有32字节的行,但所有后来的x86 CPU(包括所有x86-64)都使用64字节的行。理论上,未来的某些微体系结构可能会使用128字节的行,但是针对64字节行进行调优的多线程二进制代码非常普遍,因此这对于x86来说可能不太可能。)
由于这个原因,一些当前的实现选择根本不实现C
的特性。GCC实现了它,而clang没有(Godbolt)。当代码在结构体布局中使用它时,它就成为ABI的一部分,所以编译器在未来无法更改它以匹配未来CPU的相同目标。
GCC将建设性和破坏性都定义为64 x86-64,忽略了相邻行预取可能导致的破坏性干扰,例如在英特尔Sandybridge系列上。在高争用情况下,它不像高速缓存行内的错误共享那样灾难性,因此您可以选择只使用64字节对齐来分隔不同线程将独立访问的对象。

相关问题