为什么Crypto ++中的AES代码会产生不同的性能结果?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么Crypto ++中的AES代码会产生不同的性能结果?相关的知识,希望对你有一定的参考价值。
我正在尝试测试AES加密的性能。但每当我运行代码时,它会给出不同的结果。为什么?这是使用Crypto ++的C ++代码:
int main(int argc, char* argv[]){
AutoSeededRandomPool prng;
byte key[AES::DEFAULT_KEYLENGTH];
prng.GenerateBlock(key, sizeof(key));
byte iv[AES::BLOCKSIZE];
prng.GenerateBlock(iv, sizeof(iv));
CBC_Mode< AES >::Encryption e;
e.SetKeyWithIV(key, sizeof(key), iv);
CBC_Mode< AES >::Decryption d;
d.SetKeyWithIV(key, sizeof(key), iv);
时间测试在这里:
clock_t startTime, finishTime;
std::string plain = "AES CBC Test";
std::string cipher, encoded, recovered;
startTime = clock();
try
{
// The StreamTransformationFilter removes
// padding as required.
StringSource s(plain, true,
new StreamTransformationFilter(e,
new StringSink(cipher)
) // StreamTransformationFilter
); // StringSource
}
catch(const CryptoPP::Exception& e)
{
cerr << e.what() << endl;
exit(1);
}
// save current time just after finishing the encryption loop
finishTime = clock();
我的测试结果如下:
enter code heredouble executionTimeInSec = double( finishTime - startTime ) / CLOCK_TICKS_PER_SECOND;
std::cout << "Encryption loop execution time: " << executionTimeInSec * 1000.0 << " microseconds." << std::endl;
std::cout << "Plain text size: " << plain.size() << " bytes." << std::endl;
double data_rate_MiBps = ((double)plain.size() / 1048576) / ((double)executionTimeInSec) ;
std::cout << "Encryption/decryption loop execution time MB/S: " << data_rate_MiBps << " MB/S." << std::endl;
return 0;}
时间未经优化的调试版本。编译结果1:
加密循环执行时间:0.041微秒。
编译结果2:
加密循环执行时间:0.057微秒。
0.041微秒的测试时间太短。要获得可靠的测量,您需要执行多次测试迭代,然后将总时间除以您执行的迭代次数。
在如此短的时间范围内进行测量时,许多因素可能会影响您的时间:
- 系统上的时钟分辨率可能不够高,从而导致测量值出现相对较大的跳跃。
- 您的计时仅测量经过的时间,而不是在CPU上运行的实际时间。操作系统在一次测试中将CPU分配给其他测试而不是另一测试的影响会引起测量中的大幅波动。在进行多次迭代时,您可以在多次迭代中平滑此随机影响,从而消除机会的影响。
- 等等。
与Crypto ++基准测试相关,该库提供了cryptest.exe
的基准测试套件。你可以像下面一样调用它。 b
意味着基准; 3
意味着运行测试3秒; 2.4
表示cpu频率为2.4 GHz。
./cryptest.exe b 3 2.4
下面的命令produces output similar to。
您可以在bench1.cpp
和bench2.cpp
找到源代码。对于AES,您想要检查bench2.cpp
。这是负责生成数字的代码:
void BenchMark(const char *name, StreamTransformation &cipher, double timeTotal)
{
const int BUF_SIZE=RoundUpToMultipleOf(2048U, cipher.OptimalBlockSize());
AlignedSecByteBlock buf(BUF_SIZE);
Test::GlobalRNG().GenerateBlock(buf, BUF_SIZE);
unsigned long i=0, blocks=1;
double timeTaken;
clock_t start = ::clock();
do
{
blocks *= 2;
for (; i<blocks; i++)
cipher.ProcessString(buf, BUF_SIZE);
timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND;
}
while (timeTaken < 2.0/3*timeTotal);
OutputResultBytes(name, double(blocks) * BUF_SIZE, timeTaken);
}
在使用BenchMark
调用StreamTransformation
之前,工厂方法创建了一个AES对象并将其键入进行测试。
一些基准测试代码最近有所改变,但主要是装饰性的。最大的变化是增加了随机数发生器来测试它们的表现。另请参阅用户列表中的RNG Benchmarks and rework of RDRAND/RDSEED。
在进行基准测试时,您还应该记住Turbo Boost和其他相关技术的影响。如果您的CPU运行速度为3.5 GHz但突发频率为3.8 GHz,则会影响预期的吞吐量。有时,它使基准成为一个移动目标,而在其他时候,它可以解释为什么你超过理论最大值。
爆发只是内部超频。英特尔多年来一直在这样做。他们过去常常称之为旧P5 Pentiums中的NetBurst。通过使用支持超频的主板和处理器,硬件人员和游戏玩家一直在做这件事。
以上是关于为什么Crypto ++中的AES代码会产生不同的性能结果?的主要内容,如果未能解决你的问题,请参考以下文章