Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.

Computing Pi - how to use lambda expression

mikajlo_m_
Beginner
399 Views

Hi, every one.

I want to calculate PI using multi-core parallel algorithms. I have following code:



It seems to work well, but I can't write this with lambda expression.I tried to use example from this topic, but still something is wrong.. Please, show me how it could be look like..

[cpp]

#include <stdio.h>
#include <tbb/blocked_range.h>
#include <tbb/parallel_reduce.h>
#include <tbb/task_scheduler_init.h>


class Pi_MC
{
private:
    long num_steps;
    double step;

public:
 
    double pi;

    void operator () (const tbb::blocked_range<long> &r)
    {
        double x, sum = 0.0;

        long end = r.end();

        for (int i = r.begin(); i != end; i++)
        {
            x = (i - 0.5) * step;
            sum = sum + 4.0 / (1.0 + x*x);
        }
        pi += sum * step;
    }

    void join(Pi_MC &p)
    {
        pi += p.pi;
    }

    Pi_MC(Pi_MC &p, tbb::split)
    {
        pi = 0.0;
        num_steps = p.num_steps;
        step = p.step;
    }

    Pi_MC(long n)
    {
        pi = 0.0;
        num_steps = n;
        step = 1.0 / (double) num_steps;
    }
};


int main()
{
    tbb::task_scheduler_init init;

    const long n = 100000000;

    Pi_MC pi(n);

    tbb::parallel_reduce(tbb::blocked_range<long>(0, n, 1000000), pi);
    printf ("Pi = %.16f steps: %d \n", pi.pi, n);

    system("pause");    
}

[/cpp]

0 Kudos
6 Replies
RafSchietekat
Valued Contributor III
399 Views
Something like this perhaps (not tested): [cpp] #include <stdio.h> #include <functional> #include <tbb/blocked_range.h> #include <tbb/parallel_reduce.h> int main() { const long num_steps = 100000000; const double step = 1.0 / num_steps; const double result = tbb::parallel_reduce( tbb::blocked_range<long>(0, num_steps), 0.0, [] (const tbb::blocked_range<long> &r, const double value) -> double { double sum = 0.0; for (int i = r.begin(), end = r.end(); i != end; i++) { const double x = (i - 0.5) * step; sum += 4.0 / (1.0 + x*x); } return value + sum * step; }, std::plus<double>() ); printf ("Pi = %.16f steps: %d n", result, num_steps); system("pause"); } [/cpp] Edited on 2013-01-02, after next 3 postings: added missing "#include <functional>", and another self-indulgent "const" with the "value" parameter ("const" should have been the default all along, and "var" should have been an additional keyword...).
0 Kudos
mikajlo_m_
Beginner
399 Views
This code didn't want to be accepted: [cpp] std::plus() [/cpp] replaced it: [cpp] []( double s1, double s2 ) { return s1+s2; } [/cpp] and Viola! Happy 2013!
0 Kudos
RafSchietekat
Valued Contributor III
399 Views
Did you use "#include <functional>"? I'll assume that the template argument failed to show up because you wrote "std::plus<double>()" instead of the workaround syntax "std::plus&lt;double&gt;()" to assure correct visualisation in this forum.
0 Kudos
mikajlo_m_
Beginner
399 Views
I didnt have include.. Works! ;)
0 Kudos
RafSchietekat
Valued Contributor III
399 Views
Now for a finishing touch: does the following work instead of that for loop to determine "sum" (with "#include <numeric>", of course)? [cpp] const double sum = std::accumulate(r.begin(), r.end(), 0.0, [] (const double acc, const long i) -> double { const double x = (i - 0.5) * step; return acc + 4.0 / (1.0 + x*x); }); [/cpp] Actually using that might be a bit pedantic, though, as it doesn't really make the code more concise... although perhaps it does illustrate intent a little bit better. It could also be interesting to compare timing results, because it seems more challenging to optimise around that lambda than with a straightforward loop.
0 Kudos
mikajlo_m_
Beginner
399 Views
Ok, thx for advice!
0 Kudos
Reply