缓存大小和计算缓存集
size of cache and calculating cache set
我正在尝试了解缓存基础知识。
如果我有
#define OFFSET_BITS (6) // 64 bytes cache line
#define SET_INDEX_BITS (5) // 32 sets
#define TAG_BITS (64 - OFFSET_BITS - SET_INDEX_BITS) //
#define NWAYS (8) // 8 ways cache.
这台机器的缓存大小是多少?
它只是添加偏移量、设置和标记位吗?
另外,假设我有一个地址 0x40000100,该地址的缓存设置是什么?我该如何计算?
假设您有一个数组,如下所示:
uint8_t myCache[1 << SET_INDEX_BITS][NWAYS][1 << OFFSET_BITS];
对于NWAYS = 8
、SET_INDEX_BITS = 5
和OFFSET_BITS = 6
;数组的大小(缓存的大小)将是 16384 字节(16 KiB)。
注意"cache size"只是指缓存可以存储多少数据,不包括存储查找数据所需的标签的成本。
标签可以用第二个数组表示,如下所示:
myCacheTags[1 << SET_INDEX_BITS][NWAYS];
如果一个标签需要53位,那么256个标签需要13568位;所以要实际实现缓存,您至少需要 18080 字节。当然,在 C 语言中(你不能拥有 53 位整数数组),padding/alignment 的成本要高一些(标签数组最终每个标签的成本为 64 位)。
要在缓存中查找缓存行,您可以执行以下操作:
uint8_t *getCacheLine(uint32_t address) {
int setIndex = (address >> OFFSET_BITS) & (( 1 << SET_INDEX_BITS) - 1);
int myTag = address >> (OFFSET_BITS + SET_INDEX_BITS);
for(int way = 0; way < NWAYS; way++) {
if(myTag == myCacheTags[setIndex][way]) {
return myCache[setIndex][way];
}
}
return NULL; // Cache miss
}
注意:通常标签包含某种 "valid or invalid" 标志(以防缓存中的条目根本不包含任何内容),并且通常标签还包含一些东西来表示如何最近使用的缓存行是(用于某种 "least recently used" 驱逐算法)。我提供的示例代码不完整 - 它在执行 if(myTag == myCacheTags[setIndex][way])
时不会屏蔽掉这些额外的位,它不会检查任何 valid/invalid 标志,也不会更新标记以指示最近使用了缓存行。
我正在尝试了解缓存基础知识。 如果我有
#define OFFSET_BITS (6) // 64 bytes cache line
#define SET_INDEX_BITS (5) // 32 sets
#define TAG_BITS (64 - OFFSET_BITS - SET_INDEX_BITS) //
#define NWAYS (8) // 8 ways cache.
这台机器的缓存大小是多少? 它只是添加偏移量、设置和标记位吗? 另外,假设我有一个地址 0x40000100,该地址的缓存设置是什么?我该如何计算?
假设您有一个数组,如下所示:
uint8_t myCache[1 << SET_INDEX_BITS][NWAYS][1 << OFFSET_BITS];
对于NWAYS = 8
、SET_INDEX_BITS = 5
和OFFSET_BITS = 6
;数组的大小(缓存的大小)将是 16384 字节(16 KiB)。
注意"cache size"只是指缓存可以存储多少数据,不包括存储查找数据所需的标签的成本。
标签可以用第二个数组表示,如下所示:
myCacheTags[1 << SET_INDEX_BITS][NWAYS];
如果一个标签需要53位,那么256个标签需要13568位;所以要实际实现缓存,您至少需要 18080 字节。当然,在 C 语言中(你不能拥有 53 位整数数组),padding/alignment 的成本要高一些(标签数组最终每个标签的成本为 64 位)。
要在缓存中查找缓存行,您可以执行以下操作:
uint8_t *getCacheLine(uint32_t address) {
int setIndex = (address >> OFFSET_BITS) & (( 1 << SET_INDEX_BITS) - 1);
int myTag = address >> (OFFSET_BITS + SET_INDEX_BITS);
for(int way = 0; way < NWAYS; way++) {
if(myTag == myCacheTags[setIndex][way]) {
return myCache[setIndex][way];
}
}
return NULL; // Cache miss
}
注意:通常标签包含某种 "valid or invalid" 标志(以防缓存中的条目根本不包含任何内容),并且通常标签还包含一些东西来表示如何最近使用的缓存行是(用于某种 "least recently used" 驱逐算法)。我提供的示例代码不完整 - 它在执行 if(myTag == myCacheTags[setIndex][way])
时不会屏蔽掉这些额外的位,它不会检查任何 valid/invalid 标志,也不会更新标记以指示最近使用了缓存行。