我有下面的代码,这是我用针尖工具编写的C++ --这是一个代码的一部分,它生成一个单核系统的ITLB部分。我试图调整上面的代码,以使它与多核(例如4)一起工作。
#define CORE_NUM 4
namespace ITLB
{
// instruction TLB: 4 kB pages, 32 entries, fully associative
const UINT32 lineSize = 4*KILO;
const UINT32 cacheSize = 32 * lineSize;
const UINT32 associativity = 32;
const CACHE_ALLOC::STORE_ALLOCATION allocation = CACHE_ALLOC::STORE_ALLOCATE;
const UINT32 max_sets = cacheSize / (lineSize * associativity);
const UINT32 max_associativity = associativity;
typedef CACHE_ROUND_ROBIN(max_sets, max_associativity, allocation) CACHE;
}
LOCALVAR ITLB::CACHE itlb("ITLB 0", ITLB::cacheSize, ITLB::lineSize, ITLB::associativity);我想自动生成以下内容:
LOCALVAR ITLB::CACHE itlb_0("ITLB 0", ITLB::cacheSize, ITLB::lineSize, ITLB::associativity);
LOCALVAR ITLB::CACHE itlb_1("ITLB 1", ITLB::cacheSize, ITLB::lineSize, ITLB::associativity);
LOCALVAR ITLB::CACHE itlb_2("ITLB 2", ITLB::cacheSize, ITLB::lineSize, ITLB::associativity);
LOCALVAR ITLB::CACHE itlb_3("ITLB 3", ITLB::cacheSize, ITLB::lineSize, ITLB::associativity);因为CORE_NUM = 4,我想可能的解决方案是MACROS!有什么帮助吗?我不太熟悉宏的使用,有人能给我一个可能的解决方案吗?
发布于 2016-03-30 19:24:02
生成以序列号结尾的变量名的方法是使用宏。但是,这种方法通常会使代码复杂化。使用您可以索引的内容更干净,这是我的建议。正如Peter所指出的,在编译时知道大小和性能至关重要时,固定大小数组应该是最好的选择。在其他情况下,可能适合使用std::vector或其他集合类。
注: LOCALVAR似乎扩展到静态。如果希望将对变量的访问限制为单个源文件,则必须适当地修改我的示例。
备选案文1:
C++11,避免了预处理的复杂性,使用了std::vector。
若要将固定大小的数组替换为std::vector,而不进入预处理器,则需要ITLB::CACHE具有默认构造函数(当前情况不是这样),并正确复制可分配(未选中)。
在.h中:
#include <string>
#include <vector>
// other includes
#define CORE_NUM 4
class ItlbCachePool
{
public:
ItlbCachePool()
{
std::string namePrefix("ITLB ");
for ( std::size_t i = 0; i < CORE_NUM; ++i )
{
pool.emplace_back(
namePrefix + std::to_string(i),
ITLB::cacheSize,
ITLB::lineSize,
ITLB::associativity);
}
}
ITLB::CACHE &operator[](std::size_t index)
{
return pool[index];
}
const ITLB::CACHE &operator[](std::size_t index) const
{
return pool[index];
}
private:
std::vector<ITLB::CACHE> pool;
};
extern ItlbCachePool itlibs;在.cpp中
// ...
ItlbCachePool itlibs;用法:
const BOOL itlbHit = itlbs[coreIndex].AccessSingleLine(addr, accessType); 您可能希望在此基础上添加边界检查,并将其转换为单例。您也可以对此进行调整,以便在运行时确定内核的数量。
请注意,在构造之后,无法将元素添加到私有向量中。这将防止向量重新分配,并使对某些客户端代码可能创建的向量元素的指针/引用无效。
备选案文2:
生成一个裸数组,需要Boost库来处理预处理前的复杂性:
在.h中
#define CORE_NUM 4
extern ITLB::CACHE itlbs[CORE_NUM];在.cpp中
#include <boost/preprocessor/iteration/local.hpp>
// white space required before "(" on next line
#define BOOST_PP_LOCAL_LIMITS (0, CORE_NUM - 1)
#define BOOST_PP_LOCAL_MACRO(n) \
ITLB::CACHE( \
"ITLB " #n, ITLB::cacheSize, ITLB::lineSize, ITLB::associativity),
ITLB::CACHE itlbs[] =
{
#include BOOST_PP_LOCAL_ITERATE()
};用法:
const BOOL itlbHit = itlbs[coreIndex].AccessSingleLine(addr, accessType); 发布于 2016-03-31 03:37:59
是否需要每个ITLB对象来实际存储cacheSize、lineSize等常量?除非您是在模拟异构多核(big.LITTLE),否则这似乎是一种巨大的浪费。
最好设置一下,这样使用这些对象的代码就可以看到ITLB::associativity常量。
正如answer的答案所示,您应该使用一个向量或其他东西来保存ITLB,这样您就可以迭代它们,而不必复制/粘贴代码来使用四个不同名称的变量。
由于内核的数量也是编译时常量,所以应该使用数组,而不是std::vector,因此与访问单个变量相比,没有任何开销。
您可能也不应该在对象中存储std::string名称。将它们放在数组中可以通过进行指针运算来找到其编号:
#include <iostream>
#include <cstdint>
#define MAX_CORE 4
struct ITLB {
static const uint32_t page_size = 4*1024;
static const uint32_t cacheSize = 32 * page_size;
static const uint32_t associativity = 32;
static const uint32_t max_sets = cacheSize / (page_size * associativity);
// probably make this private
struct { uint64_t from, to; } entries[max_sets][associativity];
// write a default constructor if you want
};
static ITLB all_itlbs[MAX_CORE]; // or initialize with = { ... };
void foo(ITLB *itlb) {
std::cout << "Caller passed the ITLB for core " << itlb - all_itlbs;
std::cout << "\nIts associativity is " << itlb->associativity << '\n';
}这使得ITLB是一种POD类型,在某些情况下可能会让编译器编写更好的代码。
使用static const成员编写代码可以让您编写类似于int foo = itlb->associativity;的代码,并使其成为编译时常量。但是,如果不更改代码的用户,ITLB::page_size可能是一个非静态成员变量。代码的用户不必更改以支持异构的ITLB。
您需要注意访问ITLB::entries的方式。如果associativity不是编译时常量,那么它不能只是一个多维数组。您仍然可以使用一个固定大小的数组,如果您使用像entries[set * associativity + way_within_set]这样索引的平面数组来“模拟”多维数组,那么较小的TLB就会留下一些未使用的TLBs。
顺便说一句,这个associativity+<<+!'\n!'; } ')),filterAsm:(commentOnly:!t,directives:!t,intel:!t,labels:!t),version:3)">实际上,正如您从asm中看到的那样,itlb - all_itlbs计算只是变成减法和右移9(因为sizeof(ITLB)是512)。
发布于 2016-03-30 16:06:41
也许这能帮到你
#define fun(a, b, num) LOCALVAR ITLB::CACHE a ## num (#b " " #num, ITLB::cacheSize, ITLB::lineSize, ITLB::associativity)
fun(itlb_, ITLB, 0);
fun(itlb_, ITLB, 1);
fun(itlb_, ITLB, 2);
fun(itlb_, ITLB, 3); 将扩展到
LOCALVAR ITLB::CACHE itlb_0 ("ITLB" " " "0", ITLB::cacheSize, ITLB::lineSize, ITLB::associativity);
LOCALVAR ITLB::CACHE itlb_1 ("ITLB" " " "1", ITLB::cacheSize, ITLB::lineSize, ITLB::associativity);
LOCALVAR ITLB::CACHE itlb_2 ("ITLB" " " "2", ITLB::cacheSize, ITLB::lineSize, ITLB::associativity);
LOCALVAR ITLB::CACHE itlb_3 ("ITLB" " " "3", ITLB::cacheSize, ITLB::lineSize, ITLB::associativity);"ITLB“”"0“部分与"ITLB 0”相当。
不那么优雅,也可能很丑,但它能像你想的那样工作。
https://stackoverflow.com/questions/36313532
复制相似问题