英特尔酷睿i7具有每核L1和L2高速缓存以及大型共享L3高速缓存.我需要知道哪种互连将多个L2连接到单个L3.我是学生,需要编写缓存子系统的粗略行为模型.它是横梁吗?一辆公共汽车?戒指?我遇到的参考文献提到了缓存的结构细节,但没有一个提到存在什么样的片上互连.
谢谢,
-neha
我正在尝试优化大型2D(井,1D处理为2D)字节数组的索引,以最大化来自相同高速缓存行的大小为64字节的连续查找次数.每次查找都与前一次相同,在水平和垂直之间交替.运动是正面的还是负面的可以被视为随机的(实际上它遵循Langton的蚂蚁规则RLR,但我不认为这些信息是严格相关的),这意味着路径混乱,倾向于保持在相同的一般区域中相当长的时间.
通过一次正常索引一行,水平移动可能在同一缓存行内,但从不垂直移动.我的解决方案是将数组索引为8x8块,这是一个示例,好像高速缓存行大小为9,带有6x6数组:
24 25 26 33 34 35
21 22 23 30 31 32
18 19 20 27 28 39
6 7 8 15 16 17
3 4 5 12 13 14
0 1 2 9 10 11
Run Code Online (Sandbox Code Playgroud)
它没有显示3x3块,但它应该允许缓存线更多地重复使用:
.
.
.
56 57 58 59 60 61 62 63
48 49 50 51 52 53 54 55
40 41 42 43 44 45 46 47
32 33 34 35 36 37 38 39
24 25 26 27 28 29 …Run Code Online (Sandbox Code Playgroud) 试图xor一个巨大的uint32阵列我决定使用NEON协处理器.
我实现了两个c版本:
版本1:
uint32_t xor_array_ver_1(uint32_t *array, int size)
{
uint32x2_t acc = vmov_n_u32(0);
uint32_t acc1 = 0;
for (; size != 0; size -= 2) {
uint32x2_t vec;
vec = vld1_u32(array);
array += 2;
acc = veor_u32(acc, vec);
}
acc1 = vget_lane_u32(acc,0) ^ vget_lane_u32(acc,1);
return acc1;
}
Run Code Online (Sandbox Code Playgroud)
版本2:
uint32_t xor_array_ver_2(uint32_t *array, int size)
{
uint32x4_t acc = vmovq_n_u32(0);
uint32_t acc1 = 0;
for (; size != 0; size -= 4) {
uint32x4_t vec;
vec = vld1q_u32(array); …Run Code Online (Sandbox Code Playgroud) 我需要非常关注当前多线程项目中的速度/延迟.
缓存访问是我想要更好地理解的东西.而且我不清楚无锁队列(例如boost :: lockfree :: spsc_queue)如何在缓存级别访问/使用内存.
我已经看到了使用队列中需要操作的大对象的指针的队列.
如果消费者核心从队列中弹出一个元素,我认为这意味着元素(在这种情况下是一个指针)已经加载到消费者核心的L2和L1缓存中.但是要访问该元素,是否需要通过从L3缓存或互连中查找和加载元素(如果另一个线程位于不同的cpu套接字上)来访问指针本身?如果是这样,简单地发送可由消费者处理的对象副本可能更好吗?
谢谢.
从理论上讲,现代CPU更快:
~(在C)操作计算?假设所有表都适合L1缓存.
按位不是:
uint8_t bitwise_not(uint8_t arg) { return ~arg; }
Run Code Online (Sandbox Code Playgroud)
表不是:
// precalculcating table (once)
uint8_t table[0x100];
for (int i = 0; i < 0x100; ++i) { table[i] = ~static_cast<uint8_t>(i); }
// function
uint8_t table_not(uint8_t arg) { return table[arg]; }
// xor_not:
uint8_t xor_not(uint8_t arg) { return arg ^ 0xff; }
Run Code Online (Sandbox Code Playgroud)
在没有一个操作,但几十亿次操作,是否比任何逻辑操作更快地读取L1缓存?(我认为L1更快,但不能证明它.)
实际上,如何衡量它?
我只是想澄清这个概念,并且可以找到足够详细的答案,这些答案可以说明一切在硬件中的实际效果.请提供任何相关细节.
在VIPT高速缓存的情况下,存储器请求并行发送到TLB和高速缓存.
从TLB我们得到了经过翻译的物理地址.从缓存索引中我们得到标签列表(例如,来自属于一组的所有缓存行).
然后将翻译的TLB地址与标签列表匹配以找到候选者.
请问某人"实际上"如何实现这一点以及Cache模块和TLB(MMU)模块之间的连接?
我知道这依赖于具体的架构和实现.但是,当有VIPT缓存时,您知道的实现是什么?
谢谢.
我正在学习有关CPU高速缓存的信息,但是现在我仍然对高速缓存一致性协议(MESI)有误解。想象一下,我们有2个内核在共享状态下有一条缓存行。其中一个执行读取,另一个执行写入:
;mem is cached in Shared state
Thread 1 (core 1) Thread 2 (core 2)
mov rax, [mem] mov [mem], dword 1
Run Code Online (Sandbox Code Playgroud)
核心1可以观察到某些中间状态。我的意思是这样的:
Core 2将缓存行标记L1D为已修改,并将更改写入其中。core 1的L1D高速缓存仍处于Shared状态,所以读恰好读取陈旧的价值。core 1的L1D缓存中的行标记为无效。英特尔的MESI / MESIF实施中是否可能出现这种情况?
我目前正在研究C优化,并且过去的任务优化了一段代码.在其他优化(展开循环和强度降低)中,我根据缓存大小使用了阻塞(遵循英特尔关于此事的教程):
现在我想我理解为什么这种技术在这种情况下工作,其中步幅为1,它加载到缓存块中并减少访问内存中下一个位置时的未命中数.但是在我的代码中dst[dim * jj + ii]似乎遍布整个地方,因为它jj在最里面的循环中被乘以.缓存是如何解释的?dim乘以0然后是1然后2等在某个时刻它将超过块可以容纳的并且优化将是毫无意义的.我明白了吗?
然而在实践中,当我只用于拦截jj可变我没有得到加速性能我使用阻塞都没有ii和jj.所以我把它做得更快但不知道为什么.作业现在已经过去了,但我仍然不明白,而且非常令人沮丧.提前感谢您提出可能是一个非常愚蠢的问题.
void transpose(int *dst, int *src, int dim)
{
int i, j, dimi, jj,ii;
dimi = 0;
for(i=0; i < dim; i+=block_size)
{
for(j=0; j<dim; j+=block_size)
{
for(ii = i; ii < i+block_size; ii++)
{
dimi = dim * ii;
for(jj = j; jj < j+block_size; jj++)
{
dst[dim*jj + ii] = src[dimi + jj];
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud) 如果一个64字节的缓冲区被大量读/写,那么它很可能会被保存在L1中; 但有没有办法强迫这种行为?
同样,给一个核心独占访问这64个字节,并告诉它不要将数据与其他核心和内存控制器同步,这样这些64个字节总是存在于一个核心的L1中,无论CPU是否认为它经常被使用.
我当时在问一个关于计算机体系结构的问题,其中提到缓存是拆分缓存,这没有什么危险呢?