C++ 使用VS2012/VTune进行缓存评测

C++ 使用VS2012/VTune进行缓存评测,c++,caching,profiling,C++,Caching,Profiling,我正在使用以下代码进行测试: const int num = 5000; int test[num][num]; int _tmain(int argc, _TCHAR* argv[]) { while(true) { for (int i = 0; i < num; i++) { for (int j = 0; j < num; j++) { test[

我正在使用以下代码进行测试:

const int num = 5000;
int test[num][num];

int _tmain(int argc, _TCHAR* argv[])
{
    while(true)
    {
        for (int i = 0; i < num; i++)
        {
            for (int j = 0; j < num; j++)
            {
                test[j][i] = 10;
            }
        }
    }
}
const int num=5000;
整数测试[num][num];
int _tmain(int argc,_TCHAR*argv[]
{
while(true)
{
for(int i=0;i
我有以下Windows计数器:

  • \缓存\复制读取命中率%
  • \缓存\复制读取/秒
  • \内存\页面错误/秒
性能会话后,结果如下所示:

有人能解释一下为什么它仍然有页面错误吗? 我还运行了相同的程序,将I和j反转,试图滥用缓存。 由于我意识到我的CPU可能会检测到跨步访问,我也尝试了随机访问,但这些windows计数器的结果变化不大

我也在VTune放大器中尝试过,得到了类似的奇怪结果。 使用以下方法,随机访问或翻转i和j可以减少缓存未命中: 试验[i][j]=20; 是否给我0缓存未命中(或关闭) 我正在使用以下计数器:

  • L2_RQSTS_小姐
  • L2_RQSTS_参考
这三种方法都给了我大约7000000个参考和3800000个遗漏。在25秒的样本上。 我预计[I][j]访问几乎不会出现任何遗漏,因为它具有空间位置性,并且是可预测的


我是否使用了正确的计数器,有什么提示吗?

您有一个包含25000000个元素的数组,即100M。您还没有说明二级缓存的大小,但它可能只有几个兆,那么为什么您会期望接近0个缓存未命中?您的数据将无法放入缓存中,因此您将需要在out中交换数据(也称为缓存未命中)

您的外部while在一次运行中执行了多少个循环

我建议首先修复一些迭代,这些迭代运行的时间大约是您愿意等待的时间。这样你所有的跑步都是一致的


可能是您的随机探测运行的迭代次数要少得多,因为它们更频繁地错过缓存。事实上,考虑到您似乎在基于时间停止基准测试,并且您的示例的瓶颈是缓存未命中,您可能在缓存未命中次数相似后停止运行,并且没有意识到良好的顺序正在进行更多的迭代。

您是否禁用了优化?优化器可能会切换循环以优化缓存访问。是的,它是在完整的调试构建中捕获的(没有优化)。我还提到我使用了随机访问(因为没有优化,CPU可以为我正确检测跨步访问和缓存)。如果初始化int test[num][num]={1},结果是相同的?@dvasanth没有任何帮助:)运行num=10的同一个代码段会导致100%的缓存未命中(同样,假设二级缓存的请求量是二级缓存的请求量,二级缓存的未命中量是未命中的量),我还尝试将其移动到自己的函数中,以确保度量是隔离的,这给了我600k个引用。。80万次失误。。这怎么可能呢?)我将它改为运行10秒,不管怎样,计时似乎更好-num=100-150给我大约10%的缓存未命中率,num=200大约30%,250+大约50%的未命中率。我的CPU是英特尔i5-4670K。100-250将导致最大250k,这应该完全适合L2,对吗?最重要的是,即使它不适合,我也会假设它会及时预取,所以当它在缓存的末尾时,它会用额外的数据填充第一位,这样它就可以继续,是吗?5000x5000是25000000整数,也就是100M。您的Intel i5-4670K具有6百万个二级缓存,因此您的数据比缓存大得多。二级缓存使用64字节行。少量计算表明,要加载25000000整数,一次64字节(16整数)将需要每次执行while循环加载1562500。听起来你好像少了一半的东西。预取不是魔术,它会有帮助,但它不能使问题消失。一点建议,不要调整基准以使数字看起来更好。选择基准测试,运行它并处理结果。使基准保持一致,这样您就可以在更改前后进行基准测试,并进行有意义的比较。在本例中,在经过一定时间后停止是一种可怕的基准测试方法。您需要固定循环的数量,以便使用不同的访问模式可以比较相同的工作量。总时间应随不同的访问模式而变化。这就是基准测试的全部要点