我正在尝试并行化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
/////////////////////////////////////////////// /////////////////////////////////////
根据Hristo的建议更新,以便在while循环中移动声明Vaes_cipher_top * top
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-&gt; rst = 1的行) ../sim_main.cpp:80:错误:'top'未在此范围内声明(在top-&gt; rst = 0的行上) ../sim_main.cpp:84:错误:在此范围内未声明'top'(在top-&gt; clk = 1的行上) ../sim_main.cpp:89:错误:在此范围内未声明'top'(在top-&gt; 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条评论 在此网页的底部查看新评论
由于
/////////////////////////////////////////////// //////// 这是我想与大家分享的最终工作代码 ////////////////////////////////////////////////// /////////////////
#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
答案 0 :(得分: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无关,但上面的代码会泄漏内存。每次top
非零时,都会重新分配iter_count
,这在if (top->done && !set_done)
条件为真且i
仍等于0
时发生。可能你应该考虑如何解决这个问题。