【发布时间】:2016-06-27 13:24:17
【问题描述】:
我已经在 C 中实现了在 http://primates.ae/ 中找到的 PRIMATE 密码的位切片实现。我使用 SIMD 编程实现了它,所以我在我的代码中使用了 AVX2 指令集。
我目前正在尝试准确衡量我的实施效果如何,但我并不真正相信当前的数字,我得到了。以我目前的数字,我每字节大约有 200 个周期,这似乎比密码得到的要好。
目前,我的代码如下所示
#typedef u64 unsigned long long
u64 start, finish;
u64 samples[1000000];
data = calloc(4000, sizeof(unsigned char));
//Performance test on a single core, as that is the standard when computing cycles/byte.
SetThreadAffinityMask(GetCurrentThread(), 0x00000008);
//Find CPU clock speed
start = _rdtsc();
sleep(1000);
finish = _rdtsc();
cpu_frequency = finish-start;
//Take a lot of samples and use median of these.
for (int i = 0; i < 1000000; i++){
start = _rdtsc();
encrypt(data);
decrypt(data);
finish = _rdtsc();
samples[i] = finish - start;
}
qsort(samples);
u64 median = samples[500000];
double cycles_per_byte = 1 / (4000.00 / median);
我相信我的计算是正确的,所以我想知道......
- 使用 _rdtsc() 测量每个字节的周期是否错误?
- 可能是因为我没有测量专门用于我的代码的时钟周期,而是用于整个系统的时钟周期? (我不知道,如果我能看到在这种情况下我的代码独占了多少)
- 我可以在 Windows 上运行它而不是例如在 Windows 上运行它吗? linux 有很大的不同吗?
我尝试使用 GCC 和 MSVC 编译代码,但没有区别(使用 /O2 或 /O3 时,GCC 的速度大约快 1%;不记得是哪个)。我只在一个内核上运行测试,并关闭了 Intel Turboboost 和超线程。
我的完整源代码在这里: https://github.com/opolo/Bitsliced-AEAD/tree/master/Primates/APE120_Bitsliced 我的测试套件在 Ref.c 中,而位切片排列在 Primate.c 中……代码现在不是很干净,我的错。这就是为什么我之前试图给出一个例子,而不是完全 c/p 我的代码。
【问题讨论】:
-
very easy 了解
_rdtsc的措施。 -
嗨。感谢你的回答。我不怀疑 _rdtsc 测量了什么。如果我读取 cpu_frequency 变量,我可以看到它的值与我的 CPU 时钟速度相匹配,所以它必须是循环计数。然而,与其他密码相比,我的周期/字节数确实很大,这一事实让我想知道,如果使用它是错误的。如果它可能在多核环境中出现问题,或者是因为我没有测量专门用于我的代码的 CPU 周期(以防其他人这样做..我无法找到其他的周期/字节代码测量) Windows API 调用(例如 _rdtsc())。
-
进行快速的完整性检查很容易 - 使用您的密码处理大量数据 - 足够大,大约需要 10 秒的时间来处理。然后测量“挂钟”时间并除以数据中的字节数。这应该会给你一个数字,你可以依赖它作为在正确的球场 - 如果它与你的
_rdtsc测量值有很大不同,那么你知道你做错了什么(反之亦然)。 -
哦,现在我明白你的意思了。你知道你不只是测量你自己过程的周期,而是想知道这是否是大量数字的原因(对吗?)。对困惑感到抱歉。 (我会说确实是这个原因,但我对 Windows 的了解还不够,无法回答。)
-
在
sleep()周围调用rdtsc并不是在多处理器机器中找到时钟速度的明智方法。sleep()可能会导致程序被操作系统调度出去,你不知道它是否会被调度回同一个处理器(或处理器内核)。
标签: c++ c gcc benchmarking simd