我有一个任务来计算分支预测错误的惩罚(以滴答为单位),因此我编写了以下代码:
int main (int argc, char ** argv) {
unsigned long long start, end;
FILE *f;
f = fopen("output", "w");
long long int k = 0;
unsigned long long min;
int n = atoi(argv[1]);// n1 = atoi(argv[2]);
for (int i = 1; i <= n + 40; i++) {
min = 9999999999999;
for(int r = 0; r < 1000; r++) {
start = rdtsc();
for (long long int j = 0; j < 100000; j++) {
if (j % i == 0) {
k++;
}
}
end = rdtsc();
if (min > end - start) min = end - start;
}
fprintf (f, "%d %lld \n", i, min);
}
fclose (f);
return 0;
}
(rdtsc是一种以时间为单位测量时间的函数)
此代码的想法是,它定期(周期等于i)进入分支(如果(j%i == 0)),因此在某些时候它开始进行错误预测。代码的其他部分大部分是多次测量,我需要得到更精确的结果。
测试表明,分支错误预测在i = 47左右开始发生,但我不知道如何计算错误预测的确切数目以计算滴答的确切数目。谁能告诉我,如何在不使用Vtune等辅助程序的情况下做到这一点?
答案 0 :(得分:0)
这取决于您使用的处理器,通常可以使用cpuid获取有关处理器的大量信息,并且通常可以通过smbios或其他内存区域访问cpuid不提供的信息。
在没有处理器支持功能和手册的情况下,以一般级别在代码中执行此操作不会在很大程度上确定所需的信息,但根据您的查找内容和方式,此估计可能有用您的代码已编译,例如您在编译等过程中使用的标志。
通常,所谓的“镜面执行”或“推测执行”通常不会被程序观察到,因为它们的逻辑在管道中的转换被确定为未使用,然后被丢弃。
根据您在程序中使用特定指令的方式,您也许可以使用这种陈旧的缓存信息,无论是好是坏,但其中的逻辑会根据所使用的CPU的不同而有很大差异。
有关将此类技术用于特权执行的有趣示例,另请参阅Spectre和RowHammer。
有关具有与cpuid以及rdrand,rdseed和其他一些用法有关的代码的链接,请参见下面的注释。 (rdtsc)
尚不清楚您在寻找什么,但是肯定会帮助您入门并提供一些有用的示例。