如果地址-B访问倾向于访问地址-C访问,则缓存可以识别

If address-B access tends to be followed by address-C access, can the cache recognize it?

本文关键字:访问 地址 缓存 识别 倾向于 如果      更新时间:2023-10-16

我的程序中有一个内存访问模式,例如...

b1->c1  (b and c are address.)
//.... do something else ....
b2->c2
//.... do something else ....
b3->c3
.... 

是编译器/CACH/CPU,足够聪明,可以识别:
当我加载b时,应该(准备)加载相应的c

更具体地:它可以以某种方式预测我的访问模式并以某种方式进行优化吗?
大约有多少优势?

我创建了一个测试用例。结果表明它在运行时不能学习。
(在实际情况下,B有很多字段,但倾向于-> c。)

class C{
    public: int data=0;
};
class B{
    public: C* c;   int accu=0;
    public: B(){
        c=new C();
    }
    public: void doSomething(){
        accu+=c->data; //do something about c
    }
};
int main() {
    using namespace std;
    const int NUM=1000000;
    B* bs[NUM];
    for(int n=0;n<NUM;n++){
        bs[n]=new B();
    }
    for(int loop=0;loop<20;loop++){
        double accumulator=0;
        for(int n=0;n<NUM;n++){
            int iSecret = rand() % NUM;
            clock_t begin = clock();
            bs[iSecret]->doSomething();
            clock_t end = clock();
            accumulator+=double(end - begin);
        }
        double elapsed_secs = accumulator;
        std::cout<<elapsed_secs<<std::endl;
    }
}

print(每个循环时间)

如果它可以学习,以后的循环应该比以前的时间更少。

298749
306951
332946
...
337232

我认为它不能使用空间位置,因为c的地址很远。

在您的情况下,bs[iSecret]是一个地址,它试图通过doSomething()

访问其他地址c

这是用户级逻辑,用户只能通过适当地放置B和C指向的数据以利用空间位置来进行优化。

作为一个简单的例子,您是否希望编译器优化此代码?

int a[100][100];
for(int i = 0; i < 100; ++i)
for(int j = 0; j < 100; ++j)
    cout << a[j][i] << endl;

但是,这是有条件构造的情况,例如

address X:  if(condition)
            {
address Y:     //dosomething_A
            }
            else
            {
address Z:    //dosomething_B
            }

在这里,if条件在address X等。

在此条件构造中,编译器可以生成代码,该代码可以最大程度地减少管道处理器上的失速周期的惩罚(由于分支)。

此外,管道的处理器可以在运行时使用branch_predictor学习您的分支。