<?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 Hi Saurabh,  in Intel® oneAPI Math Kernel Library</title>
    <link>https://community.intel.com/t5/Intel-oneAPI-Math-Kernel-Library/Matrix-product-with-MKL/m-p/1062027#M21711</link>
    <description>&lt;P&gt;Hi S&lt;SPAN style="font-size: 13.008px; line-height: 19.512px;"&gt;aurabh,&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;

&lt;P&gt;&lt;SPAN style="font-size: 13.008px; line-height: 19.512px;"&gt;It seems&amp;nbsp;no direct mkl matrix product function can be called. (maybe some one in BLAS/LAPACK may help, like &lt;/SPAN&gt;A*AT).&amp;nbsp;&lt;SPAN style="font-size: 13.008px; line-height: 19.512px;"&gt;&amp;nbsp;In general, if there are many array operation, instead of to construct &amp;nbsp;the array to fit mkl BLAS or LAPACKnput, i may recommend you to use OpenMP to optimize the 4 layer loop directly , you may find some example in Intel C++ compiler documentation or&amp;nbsp;&lt;/SPAN&gt;&lt;A href="http://stackoverflow.com/questions/6780075/openmp-optimizations" target="_blank"&gt;http://stackoverflow.com/questions/6780075/openmp-optimizations&lt;/A&gt;&lt;/P&gt;

&lt;P&gt;&lt;SPAN style="font-size: 13.008px; line-height: 19.512px;"&gt;or call Array annotation :&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;

&lt;P&gt;&lt;A href="https://software.intel.com/en-us/blogs/2010/09/03/simd-parallelism-using-array-notation/" target="_blank"&gt;https://software.intel.com/en-us/blogs/2010/09/03/simd-parallelism-using-array-notation/&lt;/A&gt;&lt;/P&gt;

&lt;P&gt;&lt;A href="https://www.cilkplus.org/tutorial-array-notation" target="_blank"&gt;https://www.cilkplus.org/tutorial-array-notation&lt;/A&gt;&lt;/P&gt;

&lt;P&gt;&lt;SPAN style="font-size: 1em; line-height: 1.5;"&gt;Best Regards,&lt;/SPAN&gt;&lt;/P&gt;

&lt;P&gt;Ying&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Tue, 19 Jul 2016 06:08:13 GMT</pubDate>
    <dc:creator>Ying_H_Intel</dc:creator>
    <dc:date>2016-07-19T06:08:13Z</dc:date>
    <item>
      <title>Matrix product with MKL</title>
      <link>https://community.intel.com/t5/Intel-oneAPI-Math-Kernel-Library/Matrix-product-with-MKL/m-p/1062026#M21710</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;

&lt;P&gt;I want to do a complicated matrix product which is defined as&lt;/P&gt;

&lt;P&gt;C[i,j]&amp;nbsp; = \sum_{n,m} A[i,n]*A[j,n]* B[n,m] *A[i,m]*A[j,m]&amp;nbsp;&lt;/P&gt;

&lt;P&gt;&amp;nbsp;Where A and B are two matrix with size of NxN, (N~1000).&lt;/P&gt;

&lt;P&gt;To accomplish this task I just run four loops to creat the matrix C .&lt;/P&gt;

&lt;P&gt;for(int i=0;i&amp;lt;ndim;i++)&lt;/P&gt;

&lt;P&gt;for(int j=0;j&amp;lt;ndim;j++)&lt;/P&gt;

&lt;P&gt;for(int n=0;n&amp;lt;ndim;n++)&lt;/P&gt;

&lt;P&gt;for(int m=0;m&amp;lt;ndim;m++)&lt;/P&gt;

&lt;P&gt;C[i,j]&amp;nbsp; +=&amp;nbsp; A[i,n]*A[j,n]* B[n,m] *A[i,m]*A[j,m]&lt;/P&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;

&lt;P&gt;Can anyone suggest any better implementation using MKL matrix product function?&lt;/P&gt;

&lt;P&gt;Thanks in advance.&lt;/P&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 15 Jul 2016 18:05:39 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-oneAPI-Math-Kernel-Library/Matrix-product-with-MKL/m-p/1062026#M21710</guid>
      <dc:creator>Saurabh_Pradhan</dc:creator>
      <dc:date>2016-07-15T18:05:39Z</dc:date>
    </item>
    <item>
      <title>Hi Saurabh, </title>
      <link>https://community.intel.com/t5/Intel-oneAPI-Math-Kernel-Library/Matrix-product-with-MKL/m-p/1062027#M21711</link>
      <description>&lt;P&gt;Hi S&lt;SPAN style="font-size: 13.008px; line-height: 19.512px;"&gt;aurabh,&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;

&lt;P&gt;&lt;SPAN style="font-size: 13.008px; line-height: 19.512px;"&gt;It seems&amp;nbsp;no direct mkl matrix product function can be called. (maybe some one in BLAS/LAPACK may help, like &lt;/SPAN&gt;A*AT).&amp;nbsp;&lt;SPAN style="font-size: 13.008px; line-height: 19.512px;"&gt;&amp;nbsp;In general, if there are many array operation, instead of to construct &amp;nbsp;the array to fit mkl BLAS or LAPACKnput, i may recommend you to use OpenMP to optimize the 4 layer loop directly , you may find some example in Intel C++ compiler documentation or&amp;nbsp;&lt;/SPAN&gt;&lt;A href="http://stackoverflow.com/questions/6780075/openmp-optimizations" target="_blank"&gt;http://stackoverflow.com/questions/6780075/openmp-optimizations&lt;/A&gt;&lt;/P&gt;

&lt;P&gt;&lt;SPAN style="font-size: 13.008px; line-height: 19.512px;"&gt;or call Array annotation :&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;

&lt;P&gt;&lt;A href="https://software.intel.com/en-us/blogs/2010/09/03/simd-parallelism-using-array-notation/" target="_blank"&gt;https://software.intel.com/en-us/blogs/2010/09/03/simd-parallelism-using-array-notation/&lt;/A&gt;&lt;/P&gt;

&lt;P&gt;&lt;A href="https://www.cilkplus.org/tutorial-array-notation" target="_blank"&gt;https://www.cilkplus.org/tutorial-array-notation&lt;/A&gt;&lt;/P&gt;

&lt;P&gt;&lt;SPAN style="font-size: 1em; line-height: 1.5;"&gt;Best Regards,&lt;/SPAN&gt;&lt;/P&gt;

&lt;P&gt;Ying&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 19 Jul 2016 06:08:13 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-oneAPI-Math-Kernel-Library/Matrix-product-with-MKL/m-p/1062027#M21711</guid>
      <dc:creator>Ying_H_Intel</dc:creator>
      <dc:date>2016-07-19T06:08:13Z</dc:date>
    </item>
    <item>
      <title>Thanks for the suggestions.</title>
      <link>https://community.intel.com/t5/Intel-oneAPI-Math-Kernel-Library/Matrix-product-with-MKL/m-p/1062028#M21712</link>
      <description>&lt;P&gt;Thanks for the suggestions.&lt;/P&gt;</description>
      <pubDate>Wed, 20 Jul 2016 16:49:23 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-oneAPI-Math-Kernel-Library/Matrix-product-with-MKL/m-p/1062028#M21712</guid>
      <dc:creator>Saurabh_Pradhan</dc:creator>
      <dc:date>2016-07-20T16:49:23Z</dc:date>
    </item>
    <item>
      <title>I built a simple test code to</title>
      <link>https://community.intel.com/t5/Intel-oneAPI-Math-Kernel-Library/Matrix-product-with-MKL/m-p/1062029#M21713</link>
      <description>&lt;P&gt;I built a simple test code to perform this operation on array sizes of 512x512 (to keep the runtime short for the single-core case).&lt;/P&gt;

&lt;P&gt;The Intel 16 compiler has no trouble vectorizing the code, and my manual operation count combined with the fixed-function "actual cycles no halted" counter show that I am getting just under 12 FP operations per unhalted core cycle on a single KNL core.&amp;nbsp;&amp;nbsp; Since the code is dominated by multiplications, the peak performance should be slightly over 16 FP operations per cycle, so this is pretty good overall efficiency.&lt;/P&gt;

&lt;P&gt;Adding an OpenMP parallelization pragma on the outermost loop does not hurt the single-thread performance.&amp;nbsp;&amp;nbsp; The resulting code gets a speedup of more than 40x on 64 cores on a Xeon Phi 7210 (Knights Landing, 64 core, nominal 1.3 GHz).&amp;nbsp;&amp;nbsp; The small problem size helps scaling by making the problem cache-contained -- the three arrays only use 6 MiB for my slightly smaller test.&amp;nbsp;&amp;nbsp; The small problem size hurts scaling by giving each thread less work to do.&lt;/P&gt;

&lt;P&gt;My first thought was that this problem might need extensive cache blocking to run effectively, but this is not the case for cache-containable sizes.&amp;nbsp; The original problem size of 1000x1000 should fit in L3 on any single 10-core or larger Xeon E5 processor, or in the aggregate L3 of any 2-socket Xeon E5 system.&lt;/P&gt;</description>
      <pubDate>Wed, 20 Jul 2016 20:15:00 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-oneAPI-Math-Kernel-Library/Matrix-product-with-MKL/m-p/1062029#M21713</guid>
      <dc:creator>McCalpinJohn</dc:creator>
      <dc:date>2016-07-20T20:15:00Z</dc:date>
    </item>
    <item>
      <title>Thanks John.</title>
      <link>https://community.intel.com/t5/Intel-oneAPI-Math-Kernel-Library/Matrix-product-with-MKL/m-p/1062030#M21714</link>
      <description>&lt;P&gt;Thanks John.&lt;/P&gt;

&lt;P&gt;Actually I have all the array of the type complex&amp;lt;double&amp;gt; . Probably that's the reason its taking much more time. I have already implemented the openmp.&lt;/P&gt;</description>
      <pubDate>Tue, 09 Aug 2016 08:26:07 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-oneAPI-Math-Kernel-Library/Matrix-product-with-MKL/m-p/1062030#M21714</guid>
      <dc:creator>Saurabh_Pradhan</dc:creator>
      <dc:date>2016-08-09T08:26:07Z</dc:date>
    </item>
    <item>
      <title>Switching to double complex</title>
      <link>https://community.intel.com/t5/Intel-oneAPI-Math-Kernel-Library/Matrix-product-with-MKL/m-p/1062031#M21715</link>
      <description>&lt;P&gt;Switching to double complex hurts the efficiency moderately in my tests.&amp;nbsp; Using icc 16.0.3 I get about 8 FLOPS per cycle, compared to about 12 FLOPS per cycle for the non-complex version.&amp;nbsp; (Both cases run using 64 cores on a KNL Xeon Phi 7210, a matrix size of N=512, compiled with "icc -qopenmp -std=c99 -O3 -xMIC-AVX512" and run with "OMP_NUM_THREADS=64; KMP_AFFINITY=verbose,scatter".)&amp;nbsp; The FLOP counts are manual in each case, assuming each complex multiplication generates 4 multiplies and 2 adds and each complex addition generates 2 adds.&amp;nbsp;&amp;nbsp; Increasing the problem size to N=1000 does not have much impact on the effective FLOP rate -- the A and B arrays are still cacheable on KNL at this size.&lt;/P&gt;

&lt;P&gt;Sometimes it helps a lot to switch from the default interleaved storage format of complex variables to separate arrays for the real and imaginary parts.&amp;nbsp;&amp;nbsp; The compiler has to do a lot less lane swizzling and can use full-width vector operations almost all the time.&amp;nbsp;&amp;nbsp; You have to implement the complex arithmetic manually, but for a simple loop like this that should not take too long...&lt;/P&gt;</description>
      <pubDate>Tue, 09 Aug 2016 16:29:00 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-oneAPI-Math-Kernel-Library/Matrix-product-with-MKL/m-p/1062031#M21715</guid>
      <dc:creator>McCalpinJohn</dc:creator>
      <dc:date>2016-08-09T16:29:00Z</dc:date>
    </item>
    <item>
      <title>Thanks John.</title>
      <link>https://community.intel.com/t5/Intel-oneAPI-Math-Kernel-Library/Matrix-product-with-MKL/m-p/1062032#M21716</link>
      <description>&lt;P&gt;Thanks John.&lt;/P&gt;

&lt;P&gt;Once I had that thought but multiplication of 5 complex number will generate 32 term (16 real and 16 imaginary ). On top of this In my original problem there are many term like this. Is there any better way to do this analitycal multiplication?&lt;/P&gt;</description>
      <pubDate>Thu, 11 Aug 2016 08:05:17 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-oneAPI-Math-Kernel-Library/Matrix-product-with-MKL/m-p/1062032#M21716</guid>
      <dc:creator>Saurabh_Pradhan</dc:creator>
      <dc:date>2016-08-11T08:05:17Z</dc:date>
    </item>
    <item>
      <title>With separate (contiguous)</title>
      <link>https://community.intel.com/t5/Intel-oneAPI-Math-Kernel-Library/Matrix-product-with-MKL/m-p/1062033#M21717</link>
      <description>&lt;P&gt;With separate (contiguous) arrays for the real and imaginary parts, the direct implementation of matrix multiplication and addition are typically vectorized very effectively.&amp;nbsp;&amp;nbsp;&lt;/P&gt;

&lt;P&gt;With interleaved format the multiplication operation requires some ugly data motion to vectorize, so it is not surprising that separate contiguous arrays works better.&amp;nbsp;&lt;/P&gt;

&lt;P&gt;Complex addition does not require cross-lane data motion, but the 16.0.3 compiler includes some unnecessary re-loading of pointers in the inner loop that adds a bit of overhead.&lt;/P&gt;

&lt;P&gt;My test code (below) was compiled with icc 16.0.3 and the compile line:&lt;/P&gt;

&lt;BLOCKQUOTE&gt;
	&lt;P&gt;"icc -O3 -xMIC-AVX512 simple_complex_test.c tacc_timers.c -o simple_complex_test.AVX512"&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;

&lt;P&gt;Typical output shows the difference in timing and instruction counts.&amp;nbsp; On a Xeon Phi 7210, "native" complex multiplication requires more than twice as many instructions per element as the manually implemented version (with separate real and imaginary arrays) and requiring (for L2-contained data) taking about 1.7 times as long to execute.&amp;nbsp; Addition is closer, with the "native" version requiring about 1.64 times as many instructions and taking (up to) 1.22 times as long to execute.&lt;/P&gt;

&lt;BLOCKQUOTE&gt;
	&lt;P&gt;$ taskset -c 2 ./simple_complex_test.AVX512&lt;BR /&gt;
		Native Complex multiplication requires&lt;STRONG&gt; 2.827000 &lt;/STRONG&gt;cycles per element, &lt;STRONG&gt;2.691500 &lt;/STRONG&gt;instructions per element&lt;BR /&gt;
		Manual Complex multiplication requires &lt;STRONG&gt;1.668750 &lt;/STRONG&gt;cycles per element, &lt;STRONG&gt;1.254750&lt;/STRONG&gt; instructions per element&lt;BR /&gt;
		Native&amp;nbsp;&amp;nbsp; Complex multiplication sample result 8000000.000000 4000000.000000&lt;BR /&gt;
		Manual Complex multiplication sample result 8000000.000000 4000000.000000&lt;BR /&gt;
		Native Complex addition requires &lt;STRONG&gt;2.532500 &lt;/STRONG&gt;cycles per element, 1.441500 instructions per element&lt;BR /&gt;
		Manual Complex addition requires &lt;STRONG&gt;2.070000 &lt;/STRONG&gt;cycles per element, 0.879750 instructions per element&lt;BR /&gt;
		Native&amp;nbsp;&amp;nbsp; Complex addition sample result 6000.000000 2000.000000&lt;BR /&gt;
		Manual Complex addition sample result 6000.000000 2000.000000&lt;/P&gt;

	&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;

&lt;PRE class="brush:cpp;"&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;complex.h&amp;gt;
#include "tacc_timers.h"

#define N 4000

int main()
{
	int i;
	double complex a&lt;N&gt;,b&lt;N&gt;,c&lt;N&gt;;
	double a_r&lt;N&gt;,a_i&lt;N&gt;,b_r&lt;N&gt;,b_i&lt;N&gt;,c_r&lt;N&gt;,c_i&lt;N&gt;;
	unsigned long instr0, instr1, instr2, instr3;
	unsigned long cycles0, cycles1, cycles2, cycles3;
	double cycles_per_elem, instr_per_elem;

	for (i=0; i&amp;lt;N; i++) {
		a&lt;I&gt; = (double) (i+N/2) + ((double) (N-i))*_Complex_I;
		b&lt;I&gt; = (double) (N-i) + ((double) (i-N/2))*_Complex_I;
		c&lt;I&gt; = 0.0 + 0.0*_Complex_I;
		a_r&lt;I&gt; = (double) (i+N/2);
		a_i&lt;I&gt; = (double) (N-i);
		b_r&lt;I&gt; = (double) (N-i);
		b_i&lt;I&gt; = (double) (i-N/2);
		c_r&lt;I&gt; = 0.0;
		c_i&lt;I&gt; = 0.0;
	}

	cycles0 = rdpmc_actual_cycles();
	instr0 = rdpmc_instructions();
	// complex multiplication
	for (i=0; i&amp;lt;N; i++) c&lt;I&gt; = a&lt;I&gt;*b&lt;I&gt;;
	cycles1 = rdpmc_actual_cycles();
	instr1 = rdpmc_instructions();

	// equivalent on separate real and imaginary components
	for (i=0; i&amp;lt;N; i++) {
	   c_r&lt;I&gt; = a_r&lt;I&gt;*b_r&lt;I&gt; - a_i&lt;I&gt;*b_i&lt;I&gt;;
	   c_i&lt;I&gt; = a_r&lt;I&gt;*b_i&lt;I&gt; + a_i&lt;I&gt;*b_r&lt;I&gt;;
	}
	cycles2 = rdpmc_actual_cycles();
	instr2 = rdpmc_instructions();

	cycles_per_elem = (double)(cycles1-cycles0)/(double)N;
	instr_per_elem = (double)(instr1-instr0)/(double)N;
	printf("Native Complex multiplication requires %f cycles per element, %f instructions per element\n",cycles_per_elem,instr_per_elem);

	cycles_per_elem = (double)(cycles2-cycles1)/(double)N;
	instr_per_elem = (double)(instr2-instr1)/(double)N;
	printf("Manual Complex multiplication requires %f cycles per element, %f instructions per element\n",cycles_per_elem,instr_per_elem);

	printf("Native   Complex multiplication sample result %f %f\n",creal(c[N/2]),cimag(c[N/2]));
	printf("Manual   Complex multiplication sample result %f %f\n",c_r[N/2],c_i[N/2]);

	cycles0 = rdpmc_actual_cycles();
	instr0 = rdpmc_instructions();
	// complex addition
	for (i=0; i&amp;lt;N; i++) c&lt;I&gt; = a&lt;I&gt;+b&lt;I&gt;;
	cycles1 = rdpmc_actual_cycles();
	instr1 = rdpmc_instructions();

	// equivalent on separate real and imaginary components
	for (i=0; i&amp;lt;N; i++) {
		c_r&lt;I&gt; = a_r&lt;I&gt; + b_r&lt;I&gt;;
		c_i&lt;I&gt; = a_i&lt;I&gt; + b_i&lt;I&gt;;
	}
	cycles2 = rdpmc_actual_cycles();
	instr2 = rdpmc_instructions();

	cycles_per_elem = (double)(cycles1-cycles0)/(double)N;
	instr_per_elem = (double)(instr1-instr0)/(double)N;
	printf("Native Complex addition requires %f cycles per element, %f instructions per element\n",cycles_per_elem,instr_per_elem);

	cycles_per_elem = (double)(cycles2-cycles1)/(double)N;
	instr_per_elem = (double)(instr2-instr1)/(double)N;
	printf("Manual Complex addition requires %f cycles per element, %f instructions per element\n",cycles_per_elem,instr_per_elem);

	printf("Native   Complex addition sample result %f %f\n",creal(c[N/2]),cimag(c[N/2]));
	printf("Manual   Complex addition sample result %f %f\n",c_r[N/2],c_i[N/2]);

}
&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/I&gt;&lt;/N&gt;&lt;/N&gt;&lt;/N&gt;&lt;/N&gt;&lt;/N&gt;&lt;/N&gt;&lt;/N&gt;&lt;/N&gt;&lt;/N&gt;&lt;/PRE&gt;

&lt;P&gt;For completeness, the auxiliary timer routines use the "tacc_timers.h" header file:&lt;/P&gt;

&lt;PRE class="brush:cpp;"&gt;unsigned long rdpmc_instructions();
unsigned long rdpmc_actual_cycles();
&lt;/PRE&gt;

&lt;P&gt;and the "tacc_timers.c" file with the inline assembly routines:&lt;/P&gt;

&lt;PRE class="brush:cpp;"&gt;unsigned long rdpmc_instructions()
{
   unsigned a, d, c;

   c = (1&amp;lt;&amp;lt;30);
   __asm__ volatile("rdpmc" : "=a" (a), "=d" (d) : "c" (c));

   return ((unsigned long)a) | (((unsigned long)d) &amp;lt;&amp;lt; 32);;
}

unsigned long rdpmc_actual_cycles()
{
   unsigned a, d, c;

   c = (1&amp;lt;&amp;lt;30)+1;
   __asm__ volatile("rdpmc" : "=a" (a), "=d" (d) : "c" (c));

   return ((unsigned long)a) | (((unsigned long)d) &amp;lt;&amp;lt; 32);;
}
&lt;/PRE&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 11 Aug 2016 18:51:05 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-oneAPI-Math-Kernel-Library/Matrix-product-with-MKL/m-p/1062033#M21717</guid>
      <dc:creator>McCalpinJohn</dc:creator>
      <dc:date>2016-08-11T18:51:05Z</dc:date>
    </item>
  </channel>
</rss>

