算法的每字节测量周期

Measuring cycles per byte for an algorithm

我已经在 C 语言 http://primates.ae/ 中实现了 PRIMATE 密码的位切片实现。我是使用 SIMD 编程实现的,所以我在我的代码中使用了 AVX2 指令集。

我目前正在尝试准确衡量我的实施效果如何,但我并不真正相信我得到的当前数字。以我目前的数字,我得到大约每字节 200 个周期,这似乎比 over ciphers 得到的要好。

目前,我的代码如下所示

#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);

我相信我的计算是正确的,所以我想知道...

我试过用 GCC 和 MSVC 编译代码,没有区别(GCC 使用 /O2 或 /O3 大约快 1%;不记得是哪个了)。我 运行 仅在一个内核上进行测试,并关闭了 Intel Turboboost 和超线程。

我的完整源代码在这里: https://github.com/opolo/Bitsliced-AEAD/tree/master/Primates/APE120_Bitsliced 我的测试套件在 Ref.c 中,而位切片排列在 Primate.c 中......代码现在不是超级干净,我的错。这就是为什么我之前试图给出一个例子,而不是完全 c/p 我的代码。

Is it wrong to use _rdtsc() for measuring cycles per byte?

不,这是正确的方法。我更喜欢对 rdtsc 指令使用内联汇编来保证内联。这是一个依赖于实现的函数,所以你真的不知道发生了什么。特别是您不知道它是否正确地防止了乱序执行。参见 here for an inline asm solution。我不知道 x86 内部函数是做什么的。

Could the reason be that I don't measure clock cycle spent exclusively on my code, but on the system as a whole?

是的,函数调用有一些开销。在现代平台上通常有一个 O(100) 的时钟节拍开销。如果您的数据集足够大,应该无关紧要。

Could the fact that I run it on Windows instead of e.g. linux do a huge difference?


所以您没有从算法中获得想要的性能?这一切都取决于您的实施方式,所以我不会责怪您的计时功能。完善算法实现有许多复杂的问题。如果您使用内联 asm 或内在函数显式矢量化内容,请注意,与标准 C 和优化的编译器相比,较差或过度抽象的实现的性能可能更差。一个好的方法是首先编写算法的 C 实现作为基准和验证,然后开始手动优化。

encrypt/decrypt 函数在哪里?