<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<atom:link href="http://www.multicorebsp.com/forum/extern.php?action=feed&amp;fid=10&amp;type=rss" rel="self" type="application/rss+xml" />
		<title><![CDATA[The MulticoreBSP Forums / General]]></title>
		<link>http://www.multicorebsp.com/forum/index.php</link>
		<description><![CDATA[The most recent topics at The MulticoreBSP Forums.]]></description>
		<lastBuildDate>Fri, 13 Sep 2019 20:22:12 +0000</lastBuildDate>
		<generator>FluxBB</generator>
		<item>
			<title><![CDATA[MulticoreBSP on Windows using Code::Blocks]]></title>
			<link>http://www.multicorebsp.com/forum/viewtopic.php?id=27&amp;action=new</link>
			<description><![CDATA[<p>A few years later, there are many more MinGW compiler versions out there that can cause incompatibilities. If the above guide nets you missing symbol errors of the forms mcbsp_perf_*, __impl_*PThread*, or __MinGW_*, you&#039;re likely in such a situation. The cleanest solution is to build a MulticoreBSP library from source under your current Windows installation, but this is not supported and thus requires some manual tinkering.</p><p>I&#039;ve hence made sure at least one combination using a ready-to-go Code::Blocks version works as intended:<br />* MinGW + CodeBlocks version 17.12 [1,2]<br />* PThreads-win32 v2.1.9 [3]<br />* MulticoreBSP for C v2.0.4 pre-built 32-bit static library and header file [4,5]</p><p>You should use the x86 GC2 versions of the PThreads pre-built binaries, and you need both the DLL and the .a. To use MulticoreBSP for C in your Windows Code::Blocks project, simply add the bsp.h header [5] to your project and start coding. Before building, make sure to add the libmcbsp2.0.4.a [4] and libpthreadGC2.a (the x86 version!) [3] to your linker configuration as shown in [6]:</p><p><span class="postimg"><img src="http://www.multicorebsp.com/images/mcbsp-win32-1.png" alt="mcbsp-win32-1.png" /></span><br /><strong>The order of the static libraries matter</strong>-- the MulticoreBSP for C library should be linked first, because it has dependencies on the PThreads library.</p><p>Before running, make sure to put the pthreadGC2.dll (the x86 version!) [3] *in the same folder as your executable* (e.g., /path/to/project/bin/Release/ or /path/to/project/bin/Debug). Alternatively, the DLL could be added to your system&#039;s path. The final result should be as in [7]:</p><p><span class="postimg"><img src="http://www.multicorebsp.com/images/mcbsp-win32-2.png" alt="mcbsp-win32-2.png" /></span></p><p>The pre-built Win32 library [4] should work with all current and future MinGW v5.x.x and PThreads-win32 v2.9.x versions. The win64 pre-built binary (at <a href="http://www.multicorebsp.com/downloads/c/2.0.4/win64)" rel="nofollow">http://www.multicorebsp.com/downloads/c/2.0.4/win64)</a> is only compatible with the older MinGW v4.x.x.</p><p>[1] <a href="http://www.codeblocks.org/downloads/binaries#windows" rel="nofollow">http://www.codeblocks.org/downloads/binaries#windows</a><br />[2] <a href="http://sourceforge.net/projects/codeblocks/files/Binaries/17.12/Windows/codeblocks-17.12mingw-setup.exe" rel="nofollow">http://sourceforge.net/projects/codeblo … -setup.exe</a><br />[3] <a href="ftp://sourceware.org/pub/pthreads-win32/prebuilt-dll-2-9-1-release/" rel="nofollow">ftp://sourceware.org/pub/pthreads-win32 … 1-release/</a><br />[4] <a href="http://www.multicorebsp.com/downloads/c/2.0.4/win32/libmcbsp2.0.4.a" rel="nofollow">http://www.multicorebsp.com/downloads/c … bsp2.0.4.a</a><br />[5] <a href="http://www.multicorebsp.com/downloads/c/2.0.4/bsp.h" rel="nofollow">http://www.multicorebsp.com/downloads/c/2.0.4/bsp.h</a><br />[6] <a href="http://www.multicorebsp.com/images/mcbsp-win32-1.png" rel="nofollow">http://www.multicorebsp.com/images/mcbsp-win32-1.png</a><br />[7] <a href="http://www.multicorebsp.com/images/mcbsp-win32-2.png" rel="nofollow">http://www.multicorebsp.com/images/mcbsp-win32-2.png</a></p>]]></description>
			<author><![CDATA[dummy@example.com (Albert-Jan Yzelman)]]></author>
			<pubDate>Fri, 13 Sep 2019 20:22:12 +0000</pubDate>
			<guid>http://www.multicorebsp.com/forum/viewtopic.php?id=27&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[Multi-BSP: nested SPMD regions for hierarchical MulticoreBSP use]]></title>
			<link>http://www.multicorebsp.com/forum/viewtopic.php?id=28&amp;action=new</link>
			<description><![CDATA[<p>BSPlib and MulticoreBSP are first and foremost designed for the original flat BSP model as proposed by Leslie Valiant in 1990. In 2008, Leslie proposed a model where a BSP computer does not consist out of <em>p</em> processors, but out of <em>p</em> other BSP computers <strong>or</strong> <em>p</em> processors. This model is called Multi-BSP. MulticoreBSP for C supports this style of programming by supporting nested BSP runs.</p><p><strong>Basics</strong></p><p>What this means is best illustrated by an example. Consider the HP DL980 architecture; this machine consists out of two separate chipsets connected by a custom HP interconnect. Each chipset connects four sockets (and four memory controllers). Let us assume each socket contains an 8-core Intel Xeon processor. We observe three important layers in the hierarchy: first, the custom interconnect that basically binds together two mainboards so to create a single shared-memory computer; second, the four sockets connected by Intel Quick-Path Interconnect; and third, a single processor consisting out of 8 cores. This Multi-BSP description can be exploited in MulticoreBSP by using nested SPMD runs as follows:</p><div class="codebox"><pre class="vscroll"><code>#include &quot;mcbsp.h&quot;

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

void spmd1() {
    bsp_begin( 2 ); //HP custom interconnect
    bsp_init( &amp;spmd2, 0, NULL );
    spmd2();
    bsp_sync();
    if( bsp_pid() == 0 )
        printf( &quot;level-1 master thread closes nested BSP run...\n&quot; );
    bsp_end();
}

void spmd2() {
    bsp_begin( 4 ); //four sockets per Intel QPI
    bsp_init( &amp;spmd3, 0, NULL );
    spmd3();
    bsp_sync();
    if( bsp_pid() == 0 )
        printf( &quot;level-2 master thread closes nested BSP run...\n&quot; );
    bsp_end();
}

void spmd3() {
    bsp_begin( 8 ); //eight cores per processor
    //do useful work here
    bsp_end();
}

int main() {
    printf( &quot;Sequential part 1\n&quot; );

    bsp_init( &amp;spmd1, 0, NULL );
    spmd1();

    printf( &quot;Sequential part 2\n&quot; );
    return EXIT_SUCCESS;    
}</code></pre></div><p>To illustrate MulticoreBSP for C indeed handles this correctly, we compile the library with the MCBSP_SHOW_PINNING flag enabled, and run it on the HP DL980 machine (located at the Flanders ExaScience Labs) described above:</p><div class="codebox"><pre><code>Sequential part 1
Info: pinning used is 0 32
Info: pinning used is 0 8 16 24
Info: pinning used is 0 1 2 3 4 5 6 7
Info: pinning used is 32 40 48 56
Info: pinning used is 8 9 10 11 12 13 14 15
Info: pinning used is 24 25 26 27 28 29 30 31
Info: pinning used is 16 17 18 19 20 21 22 23
Info: pinning used is 32 33 34 35 36 37 38 39
Info: pinning used is 40 41 42 43 44 45 46 47
Info: pinning used is 56 57 58 59 60 61 62 63
Info: pinning used is 48 49 50 51 52 53 54 55
level-2 master thread closes nested BSP run...
level-2 master thread closes nested BSP run...
level-1 master thread closes nested BSP run...
Sequential part 2</code></pre></div><p>Two runs need not be identical, of course, as per the usual behaviour of concurrent threads. A second test run, for example, gives us:</p><div class="codebox"><pre><code>Sequential part 1
Info: pinning used is 0 32
Info: pinning used is 0 8 16 24
Info: pinning used is 0 1 2 3 4 5 6 7
Info: pinning used is 32 40 48 56
Info: pinning used is 16 17 18 19 20 21 22 23
Info: pinning used is 24 25 26 27 28 29 30 31
Info: pinning used is 8 9 10 11 12 13 14 15
Info: pinning used is 32 33 34 35 36 37 38 39
Info: pinning used is 40 41 42 43 44 45 46 47
Info: pinning used is 56 57 58 59 60 61 62 63
Info: pinning used is 48 49 50 51 52 53 54 55
level-2 master thread closes nested BSP run...
level-2 master thread closes nested BSP run...
level-1 master thread closes nested BSP run...
Sequential part 2</code></pre></div><p>This post describes but a toy example; in the ./examples/ directory in the MulticoreBSP for C distribution, the hierarchical.c example provides a Multi-BSP program that actually does a distributed computation in a hierarchical fashion. Please refer there for further illustration on how to practically use this facility.</p><p><strong>Thread pinning</strong></p><p>We proceed to describe how the pinning is computed in the hierarchical setting. If we have a machine consisting of 64 threads, and the thread numbering is consecutive with no reserved cores, then requesting <em>p</em> threads actually partitions the entire machine (1,2,...,64) into <em>p</em> parts (submachines), each consisting of consecutive threads. For example, if <em>p</em>=8, then submachine 1 is (1,2,...,8), submachine two is (9,10,...,16), ..., and submachine <em>p</em> is (57,58,...,64). Each of the <em>p</em> threads spawned will pin to the first thread number available in its assigned submachine. Starting a nested BSP run will apply the same logic, but only on the assigned submachine of the current thread; e.g., writing <em>bsp_begin(2)</em> threads within submachine two in the previous example will result in two threads which are assigned the submachines (9,10,11,12) and (13,14,15,16), respectively, and which are pinned to thread 9 and 13, respectively.</p><p>For different thread numberings (i.e., a wrapped numbering, as for instance commonly used on hyperthreading machines), the MulticoreBSP runtime will compute the necessary transformations to automatically yield the pinnings as described above. The same is true when reserved cores do occur. If evenly distributed submachines are not possible or not intended, the user can manually adapt the submachine settings using the interface exposed in <a href="http://multicorebsp.com/doxygen/d0/dd3/mcbsp-affinity_8h.html" rel="nofollow">mcbsp_afffinity.h</a> at runtime, while already in an SPMD section.</p>]]></description>
			<author><![CDATA[dummy@example.com (Albert-Jan Yzelman)]]></author>
			<pubDate>Mon, 22 Jul 2013 22:58:07 +0000</pubDate>
			<guid>http://www.multicorebsp.com/forum/viewtopic.php?id=28&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[bsp_sync()'s between bsp_push_reg()'s?]]></title>
			<link>http://www.multicorebsp.com/forum/viewtopic.php?id=23&amp;action=new</link>
			<description><![CDATA[<p>I checked the logs a while back: the issue I referred to above occurred when a process registers a new variable which incidentally had the same address as a previously registered variable, but not on all processors. This became evident in an application where mallocs, push_regs, pop_regs and frees were woven into subroutines in an incorrect fashion. It did lead to a detection of a bug related to multiple push_regs on the same pointer, which was fixed before version 1.0.0 already; not 1.0.1.</p><p>In any case, synching once should be all right, and the only thing I can think of is that some of the push_regs try to register the same address on some of your threads, like the above. In that case the last register will prevail (as per the standard). Note that in code like</p><div class="codebox"><pre><code>x=malloc(30*sizeof(double));
free(x);
y=malloc(2*sizeof(char));
assert( x != y);</code></pre></div><p>the assertion may fail, but doesn&#039;t have to, and in multithreading some threads may fail while others would not; this was the root cause in the bug I had.</p><p>Hope this helps.</p>]]></description>
			<author><![CDATA[dummy@example.com (Albert-Jan Yzelman)]]></author>
			<pubDate>Wed, 28 Nov 2012 14:46:59 +0000</pubDate>
			<guid>http://www.multicorebsp.com/forum/viewtopic.php?id=23&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[MulticoreBSP in C++: basic usage]]></title>
			<link>http://www.multicorebsp.com/forum/viewtopic.php?id=22&amp;action=new</link>
			<description><![CDATA[<p>Since MulticoreBSP is now available in C, you can use it from within C++ programs by simply including the mcbsp.h header file in <a href="http://www.parashift.com/c++-faq/include-c-hdrs-nonsystem.html" rel="nofollow">the usual way</a>.</p><p>This requires you to call C-style functions from object-oriented code, and this isn&#039;t always elegant In particular, having to start an SPMD section by pointing to a global function completely breaks the object-oriented style. To cope with this, MulticoreBSP for C (from version 1.0.1 on) includes a C++-wrapper that objectifies SPMD programs. This class is defined in the <em>mcbsp.hpp</em> header file; including this file also defines <a href="http://www.multicorebsp.com/doxygen/d4/df8/mcbsp_8h.html" rel="nofollow">all regular BSP primitives</a> (that is, there is no need to include the C-header mcbsp.h).</p><p>The C++ header <em>mcbsp.hpp</em> defines the <em>mcbsp</em> namespace which contains the abstract <em>BSP_program</em> class. An SPMD section making use of the MulticoreBSP library may simply extend this class, and then must implement <em>BSP_program</em>&#039;s purely virtual methods:</p><ul><li><p>virtual void spmd() = 0;</p></li><li><p>virtual BSP_program* newInstance() = 0;</p></li></ul><p>The first method is the entry point of the SPMD code. Each thread involved in execution of this SPMD code has its own instance of the final <em>BSP_program</em>. The second method ensures that the C++-wrapper can create new instances of the user-defined class when it wants to supply a new thread with its own instance of that class. Finally, <em>BSP_program</em> defines only one other public function:</p><ul><li><p>void begin( unsigned int P = bsp_nprocs() );</p></li></ul><p>Calling this function will start parallel execution of the SPMD code over a user-supplied number of <em>P</em> processors. If <em>P</em> is not supplied, the maximum available number of processors is used (see the description of <a href="http://multicorebsp.com/doxygen/d4/df8/mcbsp_8h.html#a0ab6568273b5988ca7fe1478a48d94ef" rel="nofollow">bsp_nprocs()</a>). The use of this class deprecates the use of bsp_end(), and bsp_init( ... ); these are implied and handled by the C++-wrapper. The use of bsp_begin( unsigned int P ) is replaced by the use of <em>BSP_program</em>::begin( unsigned int P ).</p><p>An object-oriented parallel `Hello world&#039;-example now looks as follows:</p><div class="codebox"><pre class="vscroll"><code>#include &quot;mcbsp.hpp&quot;

#include &lt;cstdlib&gt;
#include &lt;iostream&gt;

using namespace mcbsp;

class Hello_World: public BSP_program {

        protected:

                virtual void spmd() {
                        std::cout &lt;&lt; &quot;Hello world from thread &quot; &lt;&lt; bsp_pid() &lt;&lt; std::endl;
                }

                virtual BSP_program * newInstance() {
                        return new Hello_World();
                }

        public:

                Hello_World() {}
};

int main() {
        BSP_program *p = new Hello_World();
        p-&gt;begin( 2 );
        p-&gt;begin();
        delete p;
        return EXIT_SUCCESS;
}</code></pre></div><p>The example demonstrates calling <em>BSP_program</em>::begin( ... ) with and without parameters. Running on a quad-core computer, example output is:</p><div class="codebox"><pre><code>Hello world from thread Hello world from thread 01

Hello world from thread 3
Hello world from thread 2
Hello world from thread 0
Hello world from thread 1</code></pre></div><p>The order of the Hello-world printouts might change between runs, and `fusion&#039; of output streams (like with the first run on 2 threads) may or may not occur in repeated runs.</p><p>Any communication between threads still follows the usual C-style functions on contiguous in-memory bytes; the C++-wrapper does not supply object-oriented communication constructs (at present).</p>]]></description>
			<author><![CDATA[dummy@example.com (Albert-Jan Yzelman)]]></author>
			<pubDate>Sat, 17 Nov 2012 19:48:31 +0000</pubDate>
			<guid>http://www.multicorebsp.com/forum/viewtopic.php?id=22&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[Parallelising existing code: parallel for]]></title>
			<link>http://www.multicorebsp.com/forum/viewtopic.php?id=17&amp;action=new</link>
			<description><![CDATA[<p>When interested in transforming only parts of an existing codebase into BSP, one of the common patterns is to parallelise a single for-loop. In this example we parallelise the numerical integration of 4*sqrt(1-x^2), from 0 to 1, using the repeated trapezoidal rule.</p><p>The sequential operation looks as follows:</p><div class="codebox"><pre><code>#include &lt;math.h&gt;

unsigned int precision = 100000000;

double f( const double x ) {
        return 4 * sqrt( 1 - x * x );
}

double sequential() {
        const double h = 1.0 / ( (double)precision );
        double I = f( 0 ) + f( 1 );
        for( unsigned int i = 1; i &lt; precision - 1; ++i )
                I += 2 * f( i * h );
        return I / (double)(2*precision);
}</code></pre></div><p>An easy parallelisation using MulticoreBSP for C, is by cutting up the for-loop by using the unique thread identification numbers (bsp_pid()), and the total number of threads used in computation (bsp_nprocs()), as follows:</p><div class="codebox"><pre><code>void parallel() {
        bsp_begin( bsp_nprocs() );</code></pre></div><p>This signals the start of a Single Program, Multiple Data (SPMD) section. Multiple threads are started which each execute this function. The number of threads started is given by bsp_nprocs(), which, outside of an SPMD context, returns the total number of available cores on the current system.</p><div class="codebox"><pre><code>        //perform the local part of the loop
        const double h      = 1.0 / ( (double)precision );
        double partial_work = 0.0;
        bsp_push_reg( &amp;partial_work, sizeof( double ) );</code></pre></div><p>We need to register the memory area the partial_work variable corresponds to for communication, first.</p><div class="codebox"><pre><code>        unsigned int start = (unsigned int)  (  bsp_pid()  * precision / (double)bsp_nprocs());
        unsigned int end   = (unsigned int) ((bsp_pid()+1) * precision / (double)bsp_nprocs());</code></pre></div><p>This evenly distributes the loop and assigns this thread with its own unique piece of the loop.</p><div class="codebox"><pre><code>        if( bsp_pid() == 0 ) {
                partial_work += f( 0 );
                start = 1;
        }
        if( bsp_pid() == bsp_nprocs() - 1 ) {
                partial_work += f( 1 );
                end = precision - 1;
        }</code></pre></div><p>This takes care of the special cases of the repeated trapezoidal rule. We can now start the actual loop:</p><div class="codebox"><pre><code>        for( unsigned int i = start; i &lt; end; ++i )
                I += 2 * f( i * h );
        partial_work /= (double)(2*precision);</code></pre></div><p>Now each thread hols a partial result. We need to combine these to obtain the final result. The required all-to-one communication is known as a gather operation:</p><div class="codebox"><pre><code>        bsp_sync();
        if( bsp_pid() == 0 ) {
                double integral = partial_work;
                for( unsigned int s = 1; s &lt; bsp_nprocs(); ++s ) {
                        bsp_direct_get( s, &amp;partial_work, 0, &amp;partial_work, sizeof( double ) );
                        integral += partial_work;
                }</code></pre></div><p>The initial synchronisation (bsp_sync) is necessary to ensure each thread was ready with calculating its partial result, before continuing. Note this implementation makes use of the new MulticoreBSP direct_get() primitive; alternatively, each thread could have bsp_put its local contributions in an array local to thread 0, which then could have been read-out after a synchronisation:</p><div class="codebox"><pre><code>        double *buffer = NULL;
        if( bsp_pid() == 0 ) {
                buffer = (double*) malloc( bsp_nprocs() * sizeof( double ) );
                bsp_push_reg( &amp;buffer, bsp_nprocs() * sizeof( double ) );
        } else
                bsp_push_reg( &amp;buffer, 0 );
        bsp_put( 0, &amp;partial_work, &amp;buffer, bsp_pid() * sizeof( double ), sizeof( double ) );
        bsp_sync();
        if( bsp_pid() == 0 ) {
                double integral = partial_work;
                for( unsigned int s = 0; s &lt; bsp_nprocs(); ++s ) {
                        integral += buffer[ s ];
                }</code></pre></div><p>This variant is compatible with the BSPlib variant and thus also runs on distributed-memory systems. In any case, the computation is now finished:</p><div class="codebox"><pre><code>                printf( &quot;Integral is %.14lf, time taken for parallel calculation using %d threads: %f\n&quot;, integral, bsp_nprocs(), bsp_time() );
        }
        bsp_end();
}</code></pre></div><p>Instead of an all-to-one communication, an all-to-all would enable all threads to know the exact integral in the second superstep (the code region after bsp_sync). It is good to realise the cost of such a communication is the same as the all-to-one, in the BSP model.</p>]]></description>
			<author><![CDATA[dummy@example.com (Albert-Jan Yzelman)]]></author>
			<pubDate>Wed, 12 Sep 2012 20:45:53 +0000</pubDate>
			<guid>http://www.multicorebsp.com/forum/viewtopic.php?id=17&amp;action=new</guid>
		</item>
		<item>
			<title><![CDATA[Parallelising existing code: multiple SPMD areas]]></title>
			<link>http://www.multicorebsp.com/forum/viewtopic.php?id=16&amp;action=new</link>
			<description><![CDATA[<p>Sometimes only specific parts of an application may be worthwhile to parallelise, and it is not cost-effective to re-write the entire application as a single BSP program (although it is in general the <a href="http://en.wikipedia.org/wiki/Amdahl%27s_law" rel="nofollow">right thing to do</a>). MulticoreBSP for C does support multiple SPMD regions in a single code, thus making it possible to write BSP versions of only the compute-intensive highly-parallelisable parts of your application. It works by repeated application of bsp_init and bsp_begin; for example, the following code</p><div class="codebox"><pre class="vscroll"><code>#include &quot;mcbsp.h&quot;

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

void spmd1() {
        bsp_begin( 2 );
        printf( &quot;Hello world from thread %d!\n&quot;, bsp_pid() );
        bsp_end();
}

void spmd2() {
        bsp_begin( bsp_nprocs() );
        printf( &quot;Hello world from thread %d!\n&quot;, bsp_pid() );
        bsp_end();
}

int main() {
        printf( &quot;Sequential part 1\n&quot; );

        bsp_init( &amp;spmd1, 0, NULL );
        spmd1();

        printf( &quot;Sequential part 2\n&quot; );

        bsp_init( &amp;spmd2, 0, NULL );
        spmd2();

        printf( &quot;Sequential part 3\n&quot; );

        return EXIT_SUCCESS;
}</code></pre></div><p>produces a variant of</p><div class="quotebox"><blockquote><div><p>Sequential part 1<br />Hello world from thread 1!<br />Hello world from thread 0!<br />Sequential part 2<br />Hello world from thread 3!<br />Hello world from thread 2!<br />Hello world from thread 0!<br />Hello world from thread 1!<br />Sequential part 3</p></div></blockquote></div><p>(on a quadcore machine). Note the order of the `Hello world&#039; lines may differ. This may also serve as a way to gradually transform a large C code into BSP form. MulticoreBSP does incur an overhead of thread creation and initialisation every time bsp_begin is encountered, so be sure each SPMD areas indeed constitutes enough work to amortise this cost.</p>]]></description>
			<author><![CDATA[dummy@example.com (Albert-Jan Yzelman)]]></author>
			<pubDate>Sat, 01 Sep 2012 19:07:03 +0000</pubDate>
			<guid>http://www.multicorebsp.com/forum/viewtopic.php?id=16&amp;action=new</guid>
		</item>
	</channel>
</rss>
