How to rewrite my CPILL procedure to calculate Pi value, with use multithreading to shorten the time of calculation?

44 Views Asked by At

I have written procedure in C language with use MPFR library. This procedure is using Leibniz formula to compute Pi. This is console CLI application. The aim of this app is to reach the maximum possible limit to compute Pi with use Extended Long Leibniz formula. Hence the name CPILL which stand for - Compute Pi Long Leibniz. :) Here is the source code:

// Gottfried Wilhelm Leibniz iterative algorithm for Pi approximation
// CPILL - COMPUTE PI LONG LEIBNIZ
//
// Author: MARTE.BEST - Sylwester Bogusiak aka Sylvi91
// This is free code to calculate pi to an arbitrary degree of precision.
// There is no warranty or guarantee of any kind.
// The mpfr library has further restrictions.
// To Compile:
// gcc -o cpill cpill.c -lmpfr

#include <stdio.h>
#include <mpfr.h> // for floating point mumbers
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#ifdef __APPLE__
#include <mach/mach_time.h>
#else
#include <time.h>
#endif


int cpill(char *stop, unsigned int *bt){

    /* Applying Classic Leibniz Formula */
    
    /*
 for(i=0;i< *stop;i++)
 {
  term = pow(-1, i) / (2*i+1);
  sum += term;
 }
 pi = 4 * sum;

 printf("\nPI = %.16lf \n", pi);
*/
 
 mpfr_t sum3, term3, pi3, i3, n3, x3, i2, one3,two3, power3, div3, div33;
    
 mpfr_inits2 (*bt, sum3, term3, pi3, i3, n3, x3, i2, one3, two3, power3, div3, div33, NULL);

 
  
    mpfr_set_si (i3, 0, MPFR_RNDD);
    mpfr_set_si(x3, 0, MPFR_RNDD);
    mpfr_set_d (sum3, 0.0, MPFR_RNDD);
    mpfr_set_d (term3, 0.0, MPFR_RNDD);
    mpfr_set_d (div3, 0.0, MPFR_RNDD);
    mpfr_set_si (one3, -1, MPFR_RNDD);
    mpfr_set_si (two3, 2, MPFR_RNDD);
    mpfr_set_d (pi3, 0.0, MPFR_RNDD);
    mpfr_set_str (n3, stop, 10, MPFR_RNDD);
    mpfr_sub_si(i2, n3, 1, MPFR_RNDD);
    
    

 while(mpfr_cmpabs(i3,n3)<0)
 
 {     
    mpfr_sub_si(i3, i3, 1, MPFR_RNDD);

    mpfr_pow (power3, one3, x3, MPFR_RNDD);  
    mpfr_mul(div3, two3, x3, MPFR_RNDD);  
    mpfr_add_si(div3,div3,1,MPFR_RNDD);      
    mpfr_div(term3,power3,div3,MPFR_RNDD);           

    mpfr_add(sum3,sum3,term3,MPFR_RNDD);        
    mpfr_add_si(x3, x3, 1, MPFR_RNDD);

 
    //Print put last - 1 answer
        if ((mpfr_cmpabs(i3,i2)==0))
        {
        mpfr_mul_si(pi3,sum3,4,MPFR_RNDD);
        mpfr_printf ("\n===================\nPI for (n = %.*RZf): ",0,i2);
     
        mpfr_out_str (stdout, 10, *bt, pi3, MPFR_RNDD);
        printf ("\n===================\n\n");
        }
 
 
 
 }
    mpfr_mul_si(pi3,sum3,4,MPFR_RNDD);
  
    //Print put last answer
    mpfr_printf ("\n===================\nPI for (n = %.*RZf): ",0,i3);
    mpfr_out_str (stdout, 10, *bt, pi3, MPFR_RNDD);
    printf ("\n===================\n\n");
    
    mpfr_clears (sum3, term3, pi3, i3, n3, x3, i2, one3,two3, power3, div3, div33, NULL);

    return 0;
}


int main(int argc, char * argv[]){

    unsigned int b;

    char * i;
    if (argc <= 2){
        printf ("Usage: %s <number of iterations> <number of bits>\n", argv[0]);
        return 1;
    }

    i = argv[1];
    b = atoi(argv[2]);

    assert(i != NULL);
  
    assert( b >= 1);
  
    // Get system time START
    #ifdef __APPLE__
        uint64_t start = mach_absolute_time();
    #else
        clock_t start = clock();
    #endif
    
    // Run the main procedure.
    cpill(i,&b);
     
     
    // Get system time END 
    #ifdef __APPLE__
        uint64_t end = mach_absolute_time();
        mach_timebase_info_data_t timebase_info;
        mach_timebase_info(&timebase_info);
        long double diff = (end - start) * timebase_info.numer / timebase_info.denom; // nano sec
    
        printf("Your calculations took %.3Lf seconds to run.\n", diff / 1e9 );
    #else
        clock_t end = clock();
        printf("Your calculations took %.3Lf seconds to run.\n", (long double)(end - start) / CLOCKS_PER_SEC );
    #endif
    
    
    mpfr_free_cache ();
    
  return 0;
}

As You see is one thread app calculating the value of Pi. On my PC I run this app from command line as for example : ./cpill 1000000 1000 So, with two parameters. First parameter 1000000 means the limit of the steps of the main loop. Second parameter: 1000 is the precision. For example the quantity of digits in value of Pi number. The app is measuring the run time of this calculation.

Here are few results from console:

~/Programming/cmd/mpfr/cpill - pi leibniz long formula to compute pi$ ./pill 100 1000

===================
PI for (n = 99): 3.151693406071115578377765997070890365649285540185470123751471121727655262367284522657280268921018502369622553574362461586694470507312166190853692538124095603633806268574907681354671154086968848787076970065421160220171612704072602079901601112116065262828034987385908975083783671687791474625570730356461236844458891768297326955303498589673717891445933975837227026139583734835118197264967906177655853947780841367083189795270685279736228241677234698574926551518656684752129070718695317524541979928676900553663365103388795620149304814916984207941406875502866748546985666820016553096903791685250256980774108843773328584204449019052188233155541264621585251323343589812982044613814186527728727603524968410835740681886549875709407909101454648922025420711759828468385512675911767447578398530619370721794681498350528535954917141569460296025965167627806590145968436117511745214374362455077073534668436012027542567595485053901523511198392818836189682024563367519123921380724828722463826125022023916244506835937500e0
===================


===================
PI for (n = -100): 3.131592903558552764307414238276920516403054384406575651389662076501524609100952864365822982488857698349522051061799647516342711713342316944622536759229623241824761042444254415023012862629682416626272949964918647657357542352313808110052354880960286368355673178340682844430517340029500017339138569552440817437795282628177873055358567838078069840097425050482079907671713756192171701068269906467893763922853944586604486033971958379477675104979499907541912143019038896182795371672370535287521671765145469230175194109961457153561334345078920126924137889437242992317025360283754623713147264322300019789427826882491823445891252899836588080748230812233696786847829852175106267299415774397853705119140798025026249057415189124713574477549281284023376545590016142671970470517878779277122426830987240064814629783654224597892330015052294949046943523920013955921712524805126347595373629633190376993551048327654845780107797210521662133259298753556498149507899147155130618880303217110849800519645214080810546875000000e0
===================

Your calculations took 0.000 seconds to run.
~/Programming/cmd/mpfr/cpill - pi leibniz long formula to compute pi$ ./pill 1000 1000

===================
PI for (n = 999): 3.142593654340043051026127768502212378655491381805237245745646878089181568058156812867473482582957851053314840753777580334655425308891884399468696472251832391611097631948860234406643155444226824961708419396662932306446416339821638437192773161404920125422017906491634858641728463229711830672950908240122440022413505992427623516528067359553034467708963303080265736972746800366914551863691787950646171743260309727071761822248557176182415740422622670834325138786617832376117890511114798104003715217832069164924829169433059113744611595699027085770181703754109011827415419219104417289000039152572126769380596973590795684326947722407450187352865244221252002554045949867927992833273218985782631341935948296939589904420887481709755743196852372725437468242452057978184352938003020382783417287921147462694161501939923043710086811342131324219395184527976554424817246308038173310475318525177744514155238443085309185507147325672456026618274483936422288430187707306032006285625990393839401804143562912940979003906250e0
===================


===================
PI for (n = -1000): 3.140592653839792925963596502869395970451389330779724489367457783541907931239747608265172332007670207231403885276038710899938066629552214564551237742887150050440512339302537072825852760246628025562008569471700451065826106184744099667808080815231833582150382088582680381403109153574884416966097481526765388751288713410516399262636959112852138953628242082284834108451171503534254497047882779980017963927069792229344726802234438451103847655841832572370702077311840420049899134067873743943574731534484862025331003970654244445712185886888574271161389817018279103940957732439155326499802513202483808755807379511156184300749632366598259864641149398915351877644642466130457058742481140076773057259713300314619461016330394657274016717215837301275542641652668030768836364241511293348961463601228072632703155729714235865127012003822780294629588109595192761885541808814950764400185620071197110474989557903013029453176365428774927700169374154876759356679842207599378590184707737975600139179732650518417358398437500e0
===================

Your calculations took 0.001 seconds to run.


~/Programming/cmd/mpfr/cpill - pi leibniz long formula to compute pi$ ./pill 1000000 1000

===================
PI for (n = 999999): 3.141593653590793239212643633279315384259670383750121440572600846263405273474025706880000362511489330745939858992849549652492419228666620171097247916774294655539381587380559947746878136522048009869348776716752944021069520043246558650853017003442436797848188125023871704280484501637572142006586193932443666650396458951127822733189853740890805305214090382112145110800150348265140335262890958641262747319831346634471443969427755528926719161012551420781034304630306603835197852117383412565508092972858520350315007474373518066802032069691856774718762363073851798263865989556267349008932729254482863192283008425715114312069651254934077906321430164138711125951630655256281159570246808324246259149757927494381719473099514847219851447184175682590048783988434003122050969195108694596682954766873567496127296682070016135084105166637882923725417396725410561299001926199828463600580052921366392635542754725627936146405593617704264567572016349937244956105296782366140603956136678753807700559264048933982849121093750e0
===================


===================
PI for (n = -1000000): 3.141591653589793238712643383279190384197170352500105815564788342357153320348049143891718868370742260372404672225256165855800520882717447196510760623530648033716070675725104120018964272565116031403359543722136446712820865918919496487321935237901554027406802904331261357975311349050995848718439549859121555069550513221552365482244828565562528855902407055391047587964990261890191363252642727520120684727969709024727004471918014102521156716301961893751323946385023100161518295721851639242107495834051368030419097592679761602652547218813320109993323211180904219594177682146603520274847565150345153367099101635141493419177001494009235374276464194787518112586912964479765874418868035313738456427596307889215366323949904214551465977833667092658110858017901529613611597992431323937504856087621051585220410603705026835400764943566360896603986792731349991322050174605162690042601081576749200026967815700385352244890807326582086833630070611650303757256238466171543267458146631021520533977309241890907287597656250e0
===================

Your calculations took 0.550 seconds to run.
~/Programming/cmd/mpfr/cpill - pi leibniz long formula to compute pi$ ./pill 1000000000 1000

===================
PI for (n = 999999999): 3.141592654589793239462643384029502884447169399187605821037444593292191406301833993225691075346023367321015274014258209292845797734806890885472918001643625280307339775953585232237608851960148893205735717728141004652654810736313022093595712568354579677216490134045818870766008381944259899222482500431841527417460898055842568017249129659397790291242764590769548784808805128152155883630401457939706784035337575587558160774296218518092812448011920315543173108690164539001883021409584888552494829818003485722735700326528546977871614382231544116553038727882509741550288328208561497911494878031168137282794271010750943448628409138808426467187089773668729021489597611360120281497957163859465175624756231854107570177003548695247197442339290507241606134171809987704412810240460410757887935887162776911202794374777375178545609444298600566477143289314619508654729560888793719249539987794952308911349708384524276014240361387234212845706522962846417896762840102303089540817376823511608563421759754419326782226562500e0
===================


===================
PI for (n = -1000000000): 3.141592652589793238462643383529502884197169399062605820974944593260941406286208993217878575342117117319062149013281646792357516484562750260350847689082590124026822197813326443167479457425084195938203369094374830335771723577871478514374940778744193782411297186643222397064710145093610780797157941219179179651654839708369656000451552287707801793655837045907450291289902108875966433477635727336054667409546057478910745021890487734553813797286257498184033186153050639126379442082950268479659326155666533868272273039823456388304978189150368866494173282609607804010970436321253066489464106722219204933328270876672835474566155827217935456217174703022041799768441433199292664797342421837467602186648917015372518053732905012386367279591534817105231481490401657603795144119696728786924845012426668187240770275016087450222070210377718989084682834321038897711683519489352491983121401050453968299115102352069992616116636711554829506251091015159372771555185708495287158926317916396442342374939471483230590820312500e0
===================

Your calculations took 548.569 seconds to run.
~/Programming/cmd/mpfr/cpill - pi leibniz long formula to compute pi$ ./pill 1000000000000 1000
        
===================
PI for (n = 999999999999): 3.141592653590793238462644383279502884947169399375355820974944404807816406348708998629019200342117083607148081110938556647097750859599921098912859409105042957596036055826938765258352673370507548680442703694067582721597508652908325218356332725817727510353155201635679603426718096069290883459054131732929681713304368533350871302960512698946000299577028460858055128417289194744097239048739085563950270793625825481322043287811788084310180263990208210979323279870133454940107330379008663381637670574854187846973210169838767766751830371882947300229724383424783921097043541084102122167930510264380292793914259503558909178193284974750704667104482084834682298507898102693106144143910362967716015549483481537865658511230582549469563306293616915434377799072214603181333403453871046942796922647421550728892080438491987491265875554465820033765105885387635691391841910122071673349013529894667691363452476514352923304955629797448194789941290256724560002631604935336711464412273731028335532755590975284576416015625000e0
===================


===================
PI for (n = -1000000000000): 3.141592653588793238462643383279502884447169399375105820974944279807816406286208998628987950342117067982148081103126056647093844609599919145787859408128480457595547774576938521117727673248437236180381668537817552204019383637649536155848703331286473695655889574728330970613264421752884156621895928369510766974754030841229890495017449746246795564000551571077826326818389532642232791246218704510734868896295708561728120002245713344132763114727159006252368899885574319729447884583838858165518620912016418363401376760817213800474903777514173917053920304542216189495043735482269626962295505334016075691406564365129436347995929247412574972009567868873079850763801479535328386917342022914289583005752643053185328901124554455343811671807771027340669103545959314551546573047497287792732635008093130241857856843580053525391381069987105003158892925012111558655508659326589668437485599500535104421219475790028402682763406041875927002612222271609313520131544403336577186329828248467777029873104766011238098144531250e0
===================

Your calculations took 550044.623 seconds to run.

As You can see with limit set to 10 ^ 12 the main loop on one thread is running about six days (550044.623 seconds to run).

I want to break the next limit on my home PC which is number expressed as 10^15. I was thinking to use openMP library to improve my code to run in with multiple threads, to shorten the time of calculation. My PC specs is: AMD Ryzen 5 3600 6-Core Processor, 64 GB RAM, SSD 4 TB. I think I could run 10 threads on my home PC to beat the limit 10^15 during 6 days. Is anybody here able to rewrite this example source code to run with openMP faster with any additional thread? I was trying to use simple #pragma omp parallel methods with two threads set by omp_set_num_threads(2); command but the execution time was doubled not shortened. How to improve the code to shorten the time of calculations? Maybe there is other way than use openMP library? Thanks in advance for any help.

0

There are 0 best solutions below