我在C中使用OpenSSL来搜索双安全素数P.也就是说,我正在寻找素数P使得P = 2p + 1和p = 2p' + 1和p和p'也是素数。这种搜索需要很长时间,因此我使用OpenMP进行多线程处理。这是我的代码:
BIGNUM *p,*p_temp, *P, *P_temp, *temp1,*temp2;
BN_CTX *ctx;
ctx = BN_CTX_new();
p = BN_new();
p_temp = BN_new();
P = BN_new();
P_temp = BN_new();
temp1 = BN_new();
temp2 = BN_new();
int doublesafe;
int found;
int ID;
omp_set_num_threads(150);
#pragma omp parallel private(doublesafe,p_temp,P_temp,temp1,temp2,ID) shared(found,P,p,ctx)
{
ID = omp_get_thread_num();
printf("\n thread %d", ID);
found=0;
while(!found){
BN_generate_prime_ex(p_temp,1536,1,NULL,NULL,NULL);
BN_set_word(temp1,2);
BN_mul(P_temp, temp1, p_temp, ctx);
BN_add(P_temp, P_temp, BN_value_one());
doublesafe = BN_is_prime_ex(P_temp,10,ctx, NULL);
if(doublesafe){
#pragma omp critical
{
if(!found){
found = 1;
BN_mul(P, P_temp, BN_value_one(),ctx);
BN_mul(p, p_temp, BN_value_one(),ctx);
printf("\n found P! %d", ID);
}
}
}
}
}
//the parallel block for finding prime p ends here
运行此操作时,我遇到了分段错误:
>Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffb1ae8e700 (LWP 141701)]
0x00007ffff7a9b160 in BN_mod_word () from /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
>(gdb) bt
>#0 0x00007ffff7a9b160 in BN_mod_word () from /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
>#1 0x00007ffff7a9d2dd in ?? () from /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
>#2 0x00007ffff7a9dd5c in BN_generate_prime_ex () from /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
>#3 0x0000000000401e0f in main._omp_fn.0 () at myprogram.c:265
>#4 0x00007ffff77f734a in ?? () from /usr/lib/x86_64-linux-gnu/libgomp.so.1
>#5 0x00007ffff75d9184 in start_thread (arg=0x7ffb1ae8e700) at pthread_create.c:312
>#6 0x00007ffff730603d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
知道原因可能是什么?
我按照祖兰的建议更新了代码。它运行了一次,但是当我再次运行它时会抛出分段错误。更新的代码:
BIGNUM *p, *P;
BN_CTX *ctx;
ctx = BN_CTX_new();
p = BN_new();
P = BN_new();
int found=0;
omp_set_num_threads(150);
#pragma omp parallel shared(found,P,p,ctx)
{
int ID = omp_get_thread_num();
printf("\n thread %d", ID);
int doublesafe=0;
int local_found=0;
BIGNUM *P_temp, *p_temp, *temp1;
p_temp = BN_new();
P_temp = BN_new();
temp1 = BN_new();
while(!local_found){
BN_generate_prime_ex(p_temp,1536,1,NULL,NULL,NULL);
BN_set_word(temp1,2);
BN_mul(P_temp, temp1, p_temp, ctx);
BN_add(P_temp, P_temp, BN_value_one());
doublesafe = BN_is_prime_ex(P_temp,10,ctx, NULL);
if(doublesafe){
#pragma omp critical
{
if(!found){
found = 1;
BN_mul(P, P_temp, BN_value_one(),ctx);
BN_mul(p, p_temp, BN_value_one(),ctx);
printf("\n found p and P! %d", ID);
}
}
}
#pragma omp atomic read
local_found = found;
}
}
//the parallel block for finding safe prime p ends here
我得到以下seg错误:
>Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffb6171b700 (LWP 143091)]
0x00007ffff7a9700c in BN_set_word () from /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
>(gdb) bt
>#0 0x00007ffff7a9700c in BN_set_word () from /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
>#1 0x00007ffff7a97c45 in BN_CTX_get () from /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
>#2 0x00007ffff7a9d482 in BN_is_prime_fasttest_ex () from /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
>#3 0x0000000000401c36 in main._omp_fn.0 () at myprogram.c:257
>#4 0x00007ffff77f734a in ?? () from /usr/lib/x86_64-linux-gnu/libgomp.so.1
>#5 0x00007ffff75d9184 in start_thread (arg=0x7ffb6171b700) at pthread_create.c:312
>#6 0x00007ffff730603d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
>(gdb)
更新
我注意到调用函数
BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb);
和
BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, BN_GENCB *cb);
并行区域中的在大多数情况下(并非总是)抛出分段错误。当我评论这些功能时,程序运行正常。
有谁知道如何处理这个问题?
即使我遵循Tutorial on Using OpenSSL with pthreads关于有两个回调函数等的建议,我也会遇到分段错误。
答案 0 :(得分:1)
私有变量未在并行区域内初始化!你必须手动初始化它们 - 更好的是:在并行区域本身声明这些,然后它们是隐式私有的,它更容易被发现。尽可能在本地声明所有变量,并在声明处初始化它们。
同时你的found
- 循环也是错误的。如果found
被其他线程写入,则不得阅读INFORMATION_SCHEMA.COLUMNS
不受保护。即使该写入恰好受到保护。一种解决方案是use atomics,或者您可以使用取消。