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

时间:2017-03-02 20:27:17

标签: c++ cryptography aes benchmarking crypto++

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

2 个答案:

答案 0 :(得分:1)

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

在如此短的时间范围内进行测量时,许多因素可能会使您的时间陷入困境:

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

答案 1 :(得分: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