【发布时间】:2015-08-05 10:36:38
【问题描述】:
我创建了一个共享库,其中包含 4 个函数的静态 const 数据部分和代码部分。
这是我的静态 const 数据部分的详细信息,
static const u32 T0[256] = { 256 NON_ZERO value };
static const u32 T1[256] = {256 NON_ZERO value };
static const u32 T2[256] = {256 NON_ZERO value };
static const u32 T3[256] = {256 NON_ZERO value };
static const u32 T4[256] = {256 NON_ZERO value };
static const u32 T5[256] = {256 NON_ZERO value };
static const u32 T6[256] = {256 NON_ZERO value };
static const u32 T7[256] = {256 NON_ZERO value };
static const u32 T8[256] = {256 NON_ZERO value };
static const u32 T9[10] = {10 NON_ZERO value };
在静态 const 部分下方定义了不同的函数
int A();
int B();
// Access different index of T0 - T3 table
void C();
void D();
据我了解,文本/代码部分将包含可执行文件 指令,而数据部分将包含初始化的静态数据(为简单起见,在我的情况下,所有数据都是静态常量)
在 C() 函数内部,T0、T1、T2 和 T3 的不同索引以随机顺序访问。
故意在 C() 内部,我没有访问 T0[0]。
但是, 每次我调用 C() 函数时,它都会加载 T0[0],无论是否在 C() 函数中访问 T0[0]。
我的问题是数据部分的相邻内存与代码部分一起加载了多少?
我在想可能会加载整个 4KB 页面,所以每次调用 C() 函数时,都会加载整个 4KB 页面,因此 T0[0] 也随之加载。
但是,实验结果表明这个概念是不正确的。
下面我详细解释一下。
我计算了函数 C() 和不同静态常量数据之间的距离,如下所示
Base address of C - Base address of T0[0] = 3221 Bytes
Base address of C - Base address of T1[0] = 4345 Bytes
Base address of C - Base address of T2[0] = 5369 Bytes
Base address of C - Base address of T3[0] = 6393 Bytes
因此,每当调用 C() 时,仅加载 64 字节(即 T0[0] )。 T0[1], T0[2],... T0 数组的一部分 与 C() NOT LOADED 属于同一个 4KB 页面(如果加载了整个 4KB 页面,则必须加载这些页面,但实验结果显示它们没有加载)。因此我的概念是加载整个 4KB 页面内存是错误的。
编辑1:基于@nemetroid 的cmets,C() 和T0[0] 可能属于不同的页面。这就是为什么我在这里添加 C() 和 T0[0] 的基地址。
Base address of T0[0]=0xB7758D40 ,
Base address of C=0xB7758047 when T0[0] is loaded.
在其他实验中,当我添加另一个 64Byte 的静态常量(如 static const int DATA=10; )之前 静态常量 u32 T0[256] = {.....}
这些距离变成了
Base address of C - Base address of T0[0] =3385 Bytes [ =64 + Base address of C - Base address of T0[0]]
Base address of C - Base address of T1[0] = 4345+64 Bytes =4409 Bytes [=64 + Base address of C - Base address of T0[0]+1024]
Base address of C - Base address of T2[0] = 5369+64 Bytes = 5433 Bytes[=64 + Base address of C - Base address of T0[0]+2*1024]
Base address of C - Base address of T3[0] = 6393 +64 Bytes = 6457 Bytes[=64 + Base address of C - Base address of T0[0]+3*1024]
编辑1:
Base address of T0[0]=0xB775cD80 (just shifted by 64Bytes),
Base address of C=0xB775C047 ( in this case T0[0] is not loaded)
现在,虽然 T0[0] 仍然存在于与 C() 相同的 4KB 页面中(仅移动了 64 字节),但每当调用 C() 时它都不会加载。 所以我可以再次在这里'不要说连同 C(),整个 4KB 页面已加载。
你能帮我解释/理解为什么 T0[0] 总是在调用 C() 时被访问/加载,尽管它没有被访问/使用 在 C() 里面?
或任何链接以了解程序的内存布局和程序执行期间加载的内存大小。
我正在使用 Debian OS 和 gcc 编译器。
注意:要计算是否加载了 T0[0],在调用 C() 之前,我只是使用 clflush() 指令刷新了 T0[0],然后在 调用 C() 我已经使用 rdtsc() 计算了访问时间。
编辑 1: 我正在使用英特尔酷睿 i3 机器。
Size of L1=32KB, 8 way associative, cache line size=64bytes
Size of L2=256KB, 8 way associative, cache line size=64bytes
Size of L3=3MB, 12 way associative, cache line size=64bytes
【问题讨论】: