<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic How can I assign threads to OpenMP parallel sections by NUMA socket? in Software Tuning, Performance Optimization &amp; Platform Monitoring</title>
    <link>https://community.intel.com/t5/Software-Tuning-Performance/How-can-I-assign-threads-to-OpenMP-parallel-sections-by-NUMA/m-p/1159502#M6998</link>
    <description>&lt;P&gt;I'm trying to implement a partitioned SpGEMM algorithm on a multi-socket system, the goal is to distribute the multiplication work to all sockets and restrict the memory access to local socket only, so we can enjoy the best memory speed.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;IMG alt="partitoned SpGEMM algorithm" src="https://i.stack.imgur.com/5Gnt1.png" style="float:left" /&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Specially, the machine I'm using is a two-socket Intel Skylake system, with 24 cores per socket. So I was thinking about using nested parallel regions with 2 threads in the outer region, once a thread encounters the section block, it spawns to 24 threads and performs partitioned SpGEMM.&lt;/P&gt;
&lt;PRE class="brush:cpp; class-name:dark;"&gt;&amp;nbsp; omp_set_nested(1);
&amp;nbsp; omp_set_dynamic(0);

&amp;nbsp; for (int i = 0; i &amp;lt; ITERS; ++i) {

&amp;nbsp; start = omp_get_wtime();

&amp;nbsp; #pragma omp parallel sections num_threads(2)
&amp;nbsp; {
&amp;nbsp; #pragma omp section
&amp;nbsp; &amp;nbsp; &amp;nbsp; {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SpGEMM(A_upper, B, C, 24);
&amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; #pragma omp section
&amp;nbsp; &amp;nbsp; &amp;nbsp; {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SpGEMM(A_lower, B, C, 24);
&amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; }
&amp;nbsp; end = omp_get_wtime();
&amp;nbsp; ave_msec += (end - start) * 1000;&lt;/PRE&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;

&lt;PRE class="brush:bash; class-name:dark;"&gt;export OMP_PLACES=sockets
export OMP_PROC_BIND=spread
export OMP_NESTED=True
export OMP_MAX_ACTIVE_LEVELS=2

// run the program
numactl --localalloc ./partitioned_spgemm&lt;/PRE&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I can now get thread affinity correctly set up, but the performance is worse than what I would expect.&lt;/P&gt;
&lt;P&gt;A `C_upper = A_upper * B` or a `C_lower = A_lower * B` on a single socket yield to 700 MFLOPS(flop per second). The original SpGEMM `C = A * B` on two sockets yields to 900 MFLOPS (as you may know, the number is way lower than 2 * 700 MFLOPS due to NUMA access). With proper thread affinity, I was expecting my partitioned SpGEMM could hit 1400 MFLOPS, but I can only get 400 MFLOPS in my current setup.&lt;/P&gt;
&lt;P&gt;I'm using GCC-8.2.0 with OpenMP-4.5, OS Red Hat Enterprise Linux Server 7.6. The SpGEMM I'm using is an outer product based SpGEMM, it uses OpenMP parallelizing outer loops.&lt;/P&gt;
&lt;P&gt;I think it must have something to do with nested threads but can not figure it out myself. How can I solve this?&lt;/P&gt;
&lt;P&gt;I also posted the same question on &lt;A href="https://stackoverflow.com/questions/59410679/how-can-i-assign-threads-to-openmp-parallel-sections-by-numa-socket"&gt;Stackoverflow&lt;/A&gt;&amp;nbsp;for better visibility, let me know if it violates the term here and I'll delete it.&lt;/P&gt;</description>
    <pubDate>Thu, 19 Dec 2019 13:33:15 GMT</pubDate>
    <dc:creator>gu__zhixiang</dc:creator>
    <dc:date>2019-12-19T13:33:15Z</dc:date>
    <item>
      <title>How can I assign threads to OpenMP parallel sections by NUMA socket?</title>
      <link>https://community.intel.com/t5/Software-Tuning-Performance/How-can-I-assign-threads-to-OpenMP-parallel-sections-by-NUMA/m-p/1159502#M6998</link>
      <description>&lt;P&gt;I'm trying to implement a partitioned SpGEMM algorithm on a multi-socket system, the goal is to distribute the multiplication work to all sockets and restrict the memory access to local socket only, so we can enjoy the best memory speed.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;IMG alt="partitoned SpGEMM algorithm" src="https://i.stack.imgur.com/5Gnt1.png" style="float:left" /&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Specially, the machine I'm using is a two-socket Intel Skylake system, with 24 cores per socket. So I was thinking about using nested parallel regions with 2 threads in the outer region, once a thread encounters the section block, it spawns to 24 threads and performs partitioned SpGEMM.&lt;/P&gt;
&lt;PRE class="brush:cpp; class-name:dark;"&gt;&amp;nbsp; omp_set_nested(1);
&amp;nbsp; omp_set_dynamic(0);

&amp;nbsp; for (int i = 0; i &amp;lt; ITERS; ++i) {

&amp;nbsp; start = omp_get_wtime();

&amp;nbsp; #pragma omp parallel sections num_threads(2)
&amp;nbsp; {
&amp;nbsp; #pragma omp section
&amp;nbsp; &amp;nbsp; &amp;nbsp; {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SpGEMM(A_upper, B, C, 24);
&amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; #pragma omp section
&amp;nbsp; &amp;nbsp; &amp;nbsp; {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SpGEMM(A_lower, B, C, 24);
&amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; }
&amp;nbsp; end = omp_get_wtime();
&amp;nbsp; ave_msec += (end - start) * 1000;&lt;/PRE&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;

&lt;PRE class="brush:bash; class-name:dark;"&gt;export OMP_PLACES=sockets
export OMP_PROC_BIND=spread
export OMP_NESTED=True
export OMP_MAX_ACTIVE_LEVELS=2

// run the program
numactl --localalloc ./partitioned_spgemm&lt;/PRE&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I can now get thread affinity correctly set up, but the performance is worse than what I would expect.&lt;/P&gt;
&lt;P&gt;A `C_upper = A_upper * B` or a `C_lower = A_lower * B` on a single socket yield to 700 MFLOPS(flop per second). The original SpGEMM `C = A * B` on two sockets yields to 900 MFLOPS (as you may know, the number is way lower than 2 * 700 MFLOPS due to NUMA access). With proper thread affinity, I was expecting my partitioned SpGEMM could hit 1400 MFLOPS, but I can only get 400 MFLOPS in my current setup.&lt;/P&gt;
&lt;P&gt;I'm using GCC-8.2.0 with OpenMP-4.5, OS Red Hat Enterprise Linux Server 7.6. The SpGEMM I'm using is an outer product based SpGEMM, it uses OpenMP parallelizing outer loops.&lt;/P&gt;
&lt;P&gt;I think it must have something to do with nested threads but can not figure it out myself. How can I solve this?&lt;/P&gt;
&lt;P&gt;I also posted the same question on &lt;A href="https://stackoverflow.com/questions/59410679/how-can-i-assign-threads-to-openmp-parallel-sections-by-numa-socket"&gt;Stackoverflow&lt;/A&gt;&amp;nbsp;for better visibility, let me know if it violates the term here and I'll delete it.&lt;/P&gt;</description>
      <pubDate>Thu, 19 Dec 2019 13:33:15 GMT</pubDate>
      <guid>https://community.intel.com/t5/Software-Tuning-Performance/How-can-I-assign-threads-to-OpenMP-parallel-sections-by-NUMA/m-p/1159502#M6998</guid>
      <dc:creator>gu__zhixiang</dc:creator>
      <dc:date>2019-12-19T13:33:15Z</dc:date>
    </item>
  </channel>
</rss>

