【问题标题】:Why AES code in Crypto++ gives different performance results?为什么 Crypto++ 中的 AES 代码给出不同的性能结果?
【发布时间】:2017-03-02 20:27:17
【问题描述】:

我正在尝试测试 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++


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    与 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);
    }
    

    在使用StreamTransformation 调用BenchMark 之前,工厂方法创建了一个AES 对象并将其键入以进行测试。


    最近更改了一些基准测试代码,但主要是装饰性的。最大的变化是添加了随机数生成器来测试它们的性能。另请参阅用户列表中的RNG Benchmarks and rework of RDRAND/RDSEED


    在进行基准测试时,您还应该牢记 Turbo Boost 和其他相关技术的影响。如果您的 CPU 在 3.5 GHz 上运行,但在 3.8 GHz 时突增,那么它将影响预期的吞吐量。有时,它使基准成为一个移动的目标,而在其他时候,它可以解释为什么你会超过理论最大值。

    突发只是内部超频。英特尔多年来一直在这样做。他们曾经在旧的 P5 Pentium 中将其称为 NetBurst。硬件专家和游戏玩家一直在使用支持超频的主板和处理器。


    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-31
      • 1970-01-01
      • 1970-01-01
      • 2022-12-05
      • 2021-10-14
      相关资源
      最近更新 更多