/*学号=YJD201702032716 JH-C, G++ Raspberry-PI */ #include #include #include #include #include #include #include #include #include #include #include FILE * fpTxt = nullptr; unsigned long long old_nn = 0; inline void output_txt(unsigned long long count,unsigned long long n) { char buf_txtfm[256] = {0}; if ((old_nn/100000000 != n/100000000) || !fpTxt) { QDir dir("."); QString strDir = QString().sprintf("./prime_res/%016lld",n/100000000000); dir.mkpath(strDir); old_nn = n; sprintf (buf_txtfm,"./prime_res/%016lld/primer_%016lld.txt",n/100000000000,n/100000000); if (fpTxt) fclose(fpTxt); fpTxt = fopen64(buf_txtfm,"a+"); if (!fpTxt) printf("Fopen %s failed!\n",buf_txtfm); else { printf("Fopen %s succeed!\n",buf_txtfm); } fseeko64(fpTxt,0,SEEK_END); } if (fpTxt) fprintf(fpTxt,"%lld\t%lld\n",count,n); } int main(int argc, char * argv[]) { QCoreApplication app(argc,argv); QDir dir("."); dir.mkpath("./prime_res"); //开辟一个二进制的文件作为缓存,一个文本文件作为结果 FILE * fp = fopen64("./prime_res/primer.dat","ab+"); if (!fp) return -1; //要接着上次计算,读取最新的结果 fseeko64(fp,0,SEEK_END); unsigned long long fsz = ftello64(fp); unsigned long long test = 2; //首次计算,把2写入,作为第一个素数 if (fsz pbuffer( new unsigned long long [numthreads][max_buf_size]); //为并行计算分配建议缓存大小 std::shared_ptr suggest_buf_size_arr (new int [numthreads]); int * suggest_buf_size_ptr = suggest_buf_size_arr.get(); memset (suggest_buf_size_ptr,0,sizeof(int)*numthreads); //为并行计算分配当前测试位置偏移 std::shared_ptr pos_arr (new unsigned long long [numthreads]); unsigned long long * file_pos = pos_arr.get(); for (int i=0;i=max_buf_size) suggest_buf_size = max_buf_size; if (sthr_fpos!=0) { fseeko64(fp,0,SEEK_SET); rprimers_sthd = fread(buffer,sizeof(unsigned long long),suggest_buf_size,fp); sthr_fpos = 0; } bool ex_test = false; bool test_curr_ok = true; while (test_curr_ok && rprimers_sthd) { for (int i=0;itest) { ex_test = true; break; } if (test % buffer[i]==0) test_curr_ok = false; } if (ex_test) break; if (test_curr_ok) { fseeko64(fp,sthr_fpos,SEEK_SET); rprimers_sthd = fread(buffer,sizeof(unsigned long long),suggest_buf_size,fp); sthr_fpos = ftello64(fp); suggest_buf_size += 32; } } if (!test_curr_ok) { test+=2; continue; } printf ("Single Thread, Primer: %lld \r", test); fseeko64(fp,0,SEEK_END); fwrite(&test,sizeof(unsigned long long),1,fp); unsigned long long ttl = ftello64(fp)/8; output_txt(ttl,test); fflush(fp); test+=2; } //多线程 else { //用于存储新增素数的集合,顺便可以按照大小顺序排序。 std::set set_results; //计算并行规模 unsigned long long rbat = (unsigned long long)(log(test)/log(2) * (batch*1.0/(log(batch)/log(2))))/2*2; //控制并行规模 if (rbat>=1024*1024*16) rbat = 1024*1024*16; if (rbat=max_buf_size) suggest_buf_size = max_buf_size; int rprimers = 0; //需要重新读取缓存。由于绝大部分合数都在第一波缓存中被淘汰,所以这个读取行为发生的不频繁。 if (file_pos[omp_n]!=0) { m_f.lock(); fseeko64(fp,0,SEEK_SET); rprimers = fread(buffer,sizeof(unsigned long long),suggest_buf_size,fp); file_pos[omp_n] = 0; m_f.unlock(); } else rprimers = suggest_buf_size; bool ex_test = false; bool test_curr_ok = true; while (test_curr_ok && rprimers) { for (int i=0;it) { ex_test = true; break; } if (t % buffer[i]==0) test_curr_ok = false; } if (ex_test) break; if (test_curr_ok) { m_f.lock(); fseeko64(fp,file_pos[omp_n],SEEK_SET); rprimers = fread(buffer,sizeof(unsigned long long),suggest_buf_size,fp); file_pos[omp_n] = ftello64(fp); suggest_buf_size += 32; m_f.unlock(); } } if (!test_curr_ok) continue; #pragma omp critical (ccres) { set_results.insert(t); } } for (int i=0;i