为什么Crypto ++中的AES代码会产生不同的性能结果?

问题描述 投票:1回答:2

我正在尝试测试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微秒。

c++ cryptography aes benchmarking crypto++
2个回答
1
投票

0.041微秒的测试时间太短。要获得可靠的测量,您需要执行多次测试迭代,然后将总时间除以您执行的迭代次数。

在如此短的时间范围内进行测量时,许多因素可能会影响您的时间:

  1. 系统上的时钟分辨率可能不够高,从而导致测量值出现相对较大的跳跃。
  2. 您的计时仅测量经过的时间,而不是在CPU上运行的实际时间。操作系统在一次测试中将CPU分配给其他测试而不是另一测试的影响会引起测量中的大幅波动。在进行多次迭代时,您可以在多次迭代中平滑此随机影响,从而消除机会的影响。
  3. 等等。

0
投票

与Crypto ++基准测试相关,该库提供了cryptest.exe的基准测试套件。你可以像下面一样调用它。 b意味着基准; 3意味着运行测试3秒; 2.4表示cpu频率为2.4 GHz。

./cryptest.exe b 3 2.4

下面的命令produces output similar to

您可以在bench1.cppbench2.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。通过使用支持超频的主板和处理器,硬件人员和游戏玩家一直在做这件事。


enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.