【发布时间】: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指向的对象设为私有,而是将指针本身设为私有。每个线程都以一个未初始化的私有指针结束,任何使用->取消引用此类指针的尝试都会导致分段错误。将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