【问题标题】:circuit level parallel simulation of AES encryption using openmp使用openmp的AES加密的电路级并行仿真
【发布时间】:2013-11-20 21:27:22
【问题描述】:

我正在尝试并行化 C/C++ 中的已翻译程序。该程序最初是用 Verilog 硬件描述语言编写的。该程序已由翻译程序翻译成 C/C++。它是电路级 C/C++ 程序这一事实不应该有所作为。我本质上是在尝试遵循

中的方法

https://stackoverflow.com/users/2979872/user2979872

但是

当我尝试使用 openmp 进行并行化时,我遇到了 SEGMENTATION FAULT。这是代码。当我通过编写#pragma omp parallel num_threads(2) private(top) 使“top”(指向对象私有的指针)时,我得到分段错误。

/////////////////////////////////////// ///////////////////////////////////

int main(int argc, char **argv, char **env)
{
      Verilated::commandArgs(argc, argv);
      Vaes_cipher_top* top = new Vaes_cipher_top; // this is the aes object that will do the enc
      unsigned int i = 0;
      unsigned int set_done;
      unsigned int ld_set = 0;
      top->rst = 1;           // assert reset

      #pragma omp parallel num_threads(2) private(top)
       while (i < 2)
        {
              if (main_time > 10)
              {
              top->rst = 0;   // Deassert reset
              }
          if ((main_time % 10) == 1)
          {
              top->clk = 1;       // Toggle clock (posedge)
          }
          if ((main_time % 10) == 6)
          {

              top->clk = 0;
              //setting DUT values

             if(ld_set!=1 && main_time > 10)
              {
                    top -> ld = 1;
                    top -> key     =   {0x00000000,0x00000000,0x00000000,0x00000000};
                    top -> text_in =   {0x00000000,0x00000000,0x00000000,0x00000000};
                    ld_set++;
               }
              else if(ld_set == 1 && main_time > 10)
               {
                top -> ld = 0;
                 set_done = 0;
                }

            } //(main_time % 10) == 6)

            top->eval();            // Evaluate model

            if(top->done && !set_done)
            {

             print(top->key);
             print(top->text_in);
             print(top->text_out);
             ld_set = 0; //reset  
             i++;
             set_done  = 1;
            } //if(top->done)

            main_time++;            // Time passes...
        } //end of while 

        printf("\n Test Done\n");
        top->final();               // Done simulating

 delete top;

 return 0;
} //end of main

按照 Hristo 的建议尝试前进。由于竞态条件,不再出现分段错误,但结果不正确。

 int main(int argc, char **argv, char **env)
{
  Verilated::commandArgs(argc, argv);
  Vaes_cipher_top* top;  // this is the aes object that will do the enc
  unsigned int i = 0;
  unsigned int set_done;
  unsigned int ld_set = 0;
  //top->rst = 1;           // assert reset
  unsigned int iter_count = 1;

  #pragma omp parallel num_threads(2) firstprivate(iter_count,ld_set,set_done,i)
   while (i < 2)
    {
         if(iter_count)
          {
          top = new Vaes_cipher_top;
          iter_count = 0; 
          }
          if(main_time == 0)
            top-> rst = 1;  //assert reset
          if (main_time > 10)
          {
          top->rst = 0;   // Deassert reset
          }
      if ((main_time % 10) == 1)
      {
          top->clk = 1;       // Toggle clock (posedge)
      }
      if ((main_time % 10) == 6)
      {

          top->clk = 0;
          //setting DUT values

         if(ld_set!=1 && main_time > 10)
          {
                top -> ld = 1;
                top -> key     =   {0x00000000,0x00000000,0x00000000,0x00000000};
                top -> text_in =   {0x00000000,0x00000000,0x00000000,0x00000000};
                ld_set++;
           }
          else if(ld_set == 1 && main_time > 10)
           {
            top -> ld = 0;
             set_done = 0;
            }

        } //(main_time % 10) == 6)

        top->eval();            // Evaluate model

        if(top->done && !set_done)
        {

         print(top->key);
         print(top->text_in);
         print(top->text_out);
         ld_set = 0; //reset  
         i++;
         set_done  = 1;
         iter_count = 1; 
        } //if(top->done)

        main_time++;            // Time passes...
    } //end of while 

    printf("\n Test Done\n");
    top->final();               // Done simulating

     delete top;

return 0;
} //end of main

/////////////////////////////////////// /////////////////////////////////////////p>

按照 Hristo 的建议进行了更新,将声明 Vaes_cipher_top *top 移到了 while 循环中

int main(int argc, char **argv, char **env)
 {
  Verilated::commandArgs(argc, argv);
  unsigned int i = 0;
  unsigned int set_done;
  unsigned int ld_set = 0;
  //top->rst = 1;           // assert reset
  unsigned int iter_count = 1;

  #pragma omp parallel num_threads(2) firstprivate(iter_count,ld_set,set_done,i)
   while (i < 2)
    {
         if(iter_count)
          {
          Vaes_cipher_top* top;  // this is the aes object that will do the enc
          top = new Vaes_cipher_top;
          iter_count = 0; 
          }
          if(main_time == 0)
            top-> rst = 1;  //assert reset
          if (main_time > 10)
          {
          top->rst = 0;   // Deassert reset
          }
      if ((main_time % 10) == 1)
      {
          top->clk = 1;       // Toggle clock (posedge)
      }
      if ((main_time % 10) == 6)
      {

          top->clk = 0;
          //setting DUT values

         if(ld_set!=1 && main_time > 10)
          {
                top -> ld = 1;
                top -> key     =   {0x00000000,0x00000000,0x00000000,0x00000000};
                top -> text_in =   {0x00000000,0x00000000,0x00000000,0x00000000};
                ld_set++;
           }
          else if(ld_set == 1 && main_time > 10)
           {
            top -> ld = 0;
             set_done = 0;
            }

        } //(main_time % 10) == 6)

        top->eval();            // Evaluate model

        if(top->done && !set_done)
        {

         print(top->key);
         print(top->text_in);
         print(top->text_out);
         ld_set = 0; //reset  
         i++;
         set_done  = 1;
         iter_count = 1; 
        } //if(top->done)

        main_time++;            // Time passes...
    } //end of while 

    printf("\n Test Done\n");
    top->final();               // Done simulating

     delete top;

return 0;
} //end of main

/////////////////////////////////////// ///////////////////////////////////// 这是输出。所有的错误都是一样的。我放了几个

./sim_main.cpp:76: 错误:'top' 未在此范围内声明(在 top->rst=1 行) ../sim_main.cpp:80: 错误:'top' 没有在这个范围内声明(在 top->rst=0 行) ../sim_main.cpp:84:错误:“top”未在此范围内声明(在 top->clk =1 的行上) ../sim_main.cpp:89: 错误:“top”未在此范围内声明(在 top->clk=0 行)

如果你把 Vaes_cipher_top 声明周围的 if 去掉,就会变成无限循环!!! ///////////////////////////////////////// //////////////////////////////////////////

每次运行时,模拟挂起并且输出出现在不同的时间。我正在使用 2 个线程,即 num_threads(2)

    (1) This is the run where simulation terminates

key=67fd3c2821b9201521d6a87f205e3039
text_in=67fd3c2821b9201521d6a87f205e3039
Time=251,text_out=71a354729996bac975784dcdb50260d9, done= 1 on  0 of  2
i= 1
key=1a857b7f39a0290d20bbf2466b5b14e8
text_in=1a857b7f39a0290d20bbf2466b5b14e8
Time=321,text_out=da36095f53fd86a57f9d147e8e05603, done= 1 on  1 of  2
i= 1
key=67fd3c2821b9201521d6a87f205e3039
text_in=67fd3c2821b9201521d6a87f205e3039
Time=401,text_out=71a354729996bac975784dcdb50260d9, done= 1 on  0 of  2
i= 2
key=1a857b7f39a0290d20bbf2466b5b14e8
text_in=1a857b7f39a0290d20bbf2466b5b14e8
Time=601,text_out=da36095f53fd86a57f9d147e8e05603, done= 1 on  1 of  2
i= 2
key=67fd3c2821b9201521d6a87f205e3039
text_in=67fd3c2821b9201521d6a87f205e3039
Time=641,text_out=71a354729996bac975784dcdb50260d9, done= 1 on  0 of  2
i= 3
key=1a857b7f39a0290d20bbf2466b5b14e8
text_in=1a857b7f39a0290d20bbf2466b5b14e8
Time=841,text_out=da36095f53fd86a57f9d147e8e05603, done= 1 on  1 of  2
i= 3
key=67fd3c2821b9201521d6a87f205e3039
text_in=67fd3c2821b9201521d6a87f205e3039
Time=911,text_out=71a354729996bac975784dcdb50260d9, done= 1 on  0 of  2
i= 4
key=1a857b7f39a0290d20bbf2466b5b14e8
text_in=1a857b7f39a0290d20bbf2466b5b14e8
Time=991,text_out=da36095f53fd86a57f9d147e8e05603, done= 1 on  1 of  2
i= 4

 Test Done

    (2) This is the RUN where simulation DOES NOT terminate and i had to press ctrl+c   
        to abort the simulation

    key=75f1bcf47451ab0f33b58a5e1adfdd6
text_in=75f1bcf47451ab0f33b58a5e1adfdd6
Time=411,text_out=9049c33819d61de5c09aa388479ef10, done= 1 on  0 of  2
i= 1
key=75f1bcf47451ab0f33b58a5e1adfdd6
text_in=75f1bcf47451ab0f33b58a5e1adfdd6
Time=696,text_out=9049c33819d61de5c09aa388479ef10, done= 1 on  0 of  2
i= 2
key=75f1bcf47451ab0f33b58a5e1adfdd6
text_in=75f1bcf47451ab0f33b58a5e1adfdd6
Time=931,text_out=9049c33819d61de5c09aa388479ef10, done= 1 on  0 of  2
i= 3
key=75f1bcf47451ab0f33b58a5e1adfdd6
text_in=75f1bcf47451ab0f33b58a5e1adfdd6
Time=1151,text_out=9049c33819d61de5c09aa388479ef10, done= 1 on  0 of  2
i= 4
^C 

(必须按 Ctrl+c 来中止模拟。仅使用 1 个内核代替
2,为什么会发生这种情况以及如何防止这种情况发生?为什么输出
两个线程没有同时出现?这个可以吗?

请点击按钮 添加/显示 1 更多评论 在此网页底部查看新的 cmets

谢谢

/////////////////////////////////////// //////// 这是我想与大家分享的最终工作代码 ///////////////////////////////////////// ////////////////

#include <omp.h>
#include "Vaes_cipher_top.h"
#include "verilated.h"
#include "verilated_vcd_c.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>



  //#pragma omp threadprivate(top)

vluint64_t main_time = 0;       // Current simulation time
 // This is a 64-bit integer to reduce wrap over issues and
 // allow modulus.  You can also use a double, if you wish.

  double sc_time_stamp ()
{       // Called by $time in Verilog
       return main_time;           // converts to double, to match
                                              // what SystemC does
 }



int main(int argc, char **argv, char **env) 
{
      Verilated::commandArgs(argc, argv);
      srand(time(NULL));


          unsigned int set_done = 0;
          unsigned int i = 0;
          unsigned int ld_set = 0;

    #ifdef OMP
      #pragma omp parallel default(none) firstprivate(i,set_done,ld_set,main_time)
      {
          // unsigned int set_done = 0;
          // unsigned int i = 0;
          // unsigned int ld_set = 0; 
           Vaes_cipher_top* top = new Vaes_cipher_top;  // this is the aes object that will do the enc
           top->rst = 1;           // assert reset
    #endif

        while (i < 65000)
       // #pragma omp parallel for ordered schedule(static) 
       // for(i=0; (i<65000);i++)   
        {

              if (main_time > 10)
              {
                  top->rst = 0;   // Deassert reset
              }
              if ((main_time % 10) == 1)
              {
                  top->clk = 1;       // Toggle clock (posedge)
              }
              if ((main_time % 10) == 6)
              {

                  top->clk = 0;
                  //setting DUT values

              if(ld_set!=1 && main_time > 10)
               {
                  top -> ld = 1;

                  //unsigned int rand_state = time(NULL) + 1337*omp_get_thread_num();
                  //unsigned int rnd[4];      
                  //rnd[0] = rand_r(&rand_state);
                  //rnd[1] = rand_r(&rand_state);
                  //rnd[2] = rand_r(&rand_state);
                  //rnd[3] = rand_r(&rand_state);
                  top -> key     =   {rand(),rand(),rand(),rand()}; // {0x00000000,0x000000000,0x00000000,0x00000000};
                  top -> text_in =   {rand(),rand(),rand(),rand()}; //{0x00000000,0x00000000,0x00000000,0x00000000};  
                  //top -> key     =   {0x00000000,0x00000000,0x00000000,0x00000000};
                  //top -> text_in =   {0x00000000,0x00000000,0x00000000,0x00000000};
                  ld_set++;
                }
                else if(ld_set == 1 && main_time > 10)
                {
                top -> ld = 0;
                set_done = 0;
                }   

                } //(main_time % 10) == 6)

                top->eval();            // Evaluate model

                if(top->done == 1 && set_done == 0)
                {
                #ifdef OMP
                   printf("Time=%2d, key=%2x%2x%2x%2x,text_in=%2x%2x%2x%2x,text_out=%2x%2x%2x%2x on %2d of %2d\n",   \
                           main_time,top->key[3],top->key[2],top->key[1],top->key[0],                               \
                           top->text_in[3],top->text_in[2],top->text_in[1],top->text_in[0],                 \
                           top->text_out[3],top->text_out[2],top->text_out[1],top->text_out[0],top->done, \
                           omp_get_thread_num(),omp_get_num_threads()
                         );
                #else
                   printf("Time=%2d, key=%2x%2x%2x%2x,text_in=%2x%2x%2x%2x,text_out=%2x%2x%2x%2x\n" ,   \
                           main_time,top->key[3],top->key[2],top->key[1],top->key[0],                               \
                           top->text_in[3],top->text_in[2],top->text_in[1],top->text_in[0],                 \
                           top->text_out[3],top->text_out[2],top->text_out[1],top->text_out[0],top->done
                         );
                #endif

                  ld_set = 0; //reset the value 
                    i++;
                  // printf("i=%2d\n",i);
                   set_done  = 1;
                } //if(top->done)

                //#pragma omp barrier   
                main_time++;

          } //end of while


        top->final();               // Done simulating
        delete top;
      } //pragma omp

        printf("\n Test Done\n");


    return 0;
} //end of main

【问题讨论】:

  • private(top) 不会将top 指向的对象设为私有,而是将指针本身设为私有。每个线程都以一个未初始化的私有指针结束,任何使用-&gt; 取消引用此类指针的尝试都会导致分段错误。将Vaes_cipher_top* top = new Vaes_cipher_top; 语句移动到并行循环中怎么样?有些变量看起来也需要private 处理。此外,每个线程都执行相同的while 循环,并且工作不会在线程之间分配。你在测试Vaes_cipher_top 是否是线程安全的?
  • 嗨 Hristo,再次感谢您的评论。我没有测试 Vaes_cipher_top 是否是线程安全的,我只是想让它成为多线程的。其次,如您所见,我编写了 while 循环,以便每个线程执行相同的工作。一旦每个线程产生正确的结果,我将为密钥和明文生成随机数,以便每个线程在单独的明文和密钥上工作。现在事情不正常。请看上面的修改代码
  • 您仅将new 语句移到并行区域内,但将top 的定义留在了外部,它仍然是共享的。
  • 您会收到类似 ./sim_main.cpp:76 的范围错误:错误:“top”未在此范围内声明。有关更新的代码和错误消息,请参见上文
  • Hristo,只是为了让您知道。我将感谢您在源代码中帮助我的贡献。此外,此代码将开放源代码供任何人使用。

标签: c performance aes openmp simulation


【解决方案1】:

您几乎猜对了,但 Vaes_cipher_top* top; 应该移到 if 语句之前,例如紧接在while 循环的左大括号之后。同样在这种情况下,top 在并行区域之外将不可见。我会建议你重组代码如下:

int main(int argc, char **argv, char **env)
{
   Verilated::commandArgs(argc, argv);

   #pragma omp parallel num_threads(2)
   {
      unsigned int i = 0;
      unsigned int set_done;
      unsigned int ld_set = 0;
      //top->rst = 1;           // assert reset
      unsigned int iter_count = 1;
      Vaes_cipher_top* top = new Vaes_cipher_top;  // this is the aes object that will do the enc

      while (i < 2)
      {
         if (iter_count)
         {
            top = new Vaes_cipher_top;
            iter_count = 0; 
         }
         if (main_time == 0)
            top-> rst = 1;  //assert reset
         if (main_time > 10)
         {
            top->rst = 0;   // Deassert reset
         }
         if ((main_time % 10) == 1)
         {
            top->clk = 1;       // Toggle clock (posedge)
         }
         if ((main_time % 10) == 6)
         {
            top->clk = 0;
            //setting DUT values

            if (ld_set!=1 && main_time > 10)
            {
               top->ld = 1;
               top->key     = {0x00000000,0x00000000,0x00000000,0x00000000};
               top->text_in = {0x00000000,0x00000000,0x00000000,0x00000000};
               ld_set++;
            }
            else if (ld_set == 1 && main_time > 10)
            {
               top->ld = 0;
               set_done = 0;
            }
         } //(main_time % 10) == 6)

         top->eval();            // Evaluate model

         if (top->done && !set_done)
         {
            print(top->key);
            print(top->text_in);
            print(top->text_out);
            ld_set = 0; //reset  
            i++;
            set_done  = 1;
            iter_count = 1; 
         } //if(top->done)

         main_time++;            // Time passes...
      } //end of while 

      top->final();               // Done simulating

      delete top;
   }

   printf("\nTest Done\n");

   return 0;
} //end of main

虽然这与 OpenMP 无关,但上面的代码会泄漏内存。每次iter_count 为非零时,top 都会重新分配,这发生在if (top-&gt;done &amp;&amp; !set_done) 条件为真且i 仍等于0 时。或许您应该考虑如何解决这个问题。

【讨论】:

  • 让我试试那个代码。我会在一小时内回复你更新。非常感谢。
  • Hristo 老兄!这是工作。万岁!!!首先,我衷心感谢您和 stackoverflow 社区提供了这样一个奇妙而友好的平台。我将把你的名字放在源代码中,并尽快使其开源。我会及时通知你。如果您可以通过电子邮件将您的联系方式发送给我,您可以发布有关开源代码的信息。再次感谢
  • 我在模拟中注意到一件事,那就是模拟有时会挂起。此外,当我重新运行模拟时,每次运行时密文都会出现在不同的时间。请参见上面的示例。如何解决这个问题
  • 当我为纯文本和密钥添加随机化时,模拟挂起。如果我不添加随机化并让密钥和明文为 0,如您的解决方案中所示,模拟在大多数情况下都不会挂起。但是在 5 次运行中,它仍然会挂起,明文和密钥为 0。而在明文和密钥是随机的情况下,它大部分时间都会挂起,例如 10 次运行中的 8 次。
  • 在串行模式下运行时是否挂起,例如使用 num_threads(1) 还是在编译期间禁用 OpenMP?
猜你喜欢
  • 2015-03-15
  • 2012-12-17
  • 1970-01-01
  • 2010-10-11
  • 2011-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多