<?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 MATMUL in Intel® Fortran Compiler</title>
    <link>https://community.intel.com/t5/Intel-Fortran-Compiler/MATMUL/m-p/1406127#M162315</link>
    <description>&lt;P&gt;On the Fortran discourse site, there has been a discussion about matmul. The notes include a comparison of the results for different compilers and machines.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Running the program on IFORT in 32 bit mode, (no idea why 64 bit mode was slower). On a DELL Precision 5570 - Core I7 - 11850H with 32GB memory and a Samsung M2 drive, I get the analysis times shown on the graphs. The first graph is the run time as documented in the program and the second is the cubic root of the run time.&amp;nbsp; A linear regression shows the time starts to climb above cubic past 6000 by a little bit.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;No other programs running.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="fortran"&gt;module maprod_mod
    implicit none
    private
    public :: maprod, RP
    integer, parameter :: RP = kind(0.0D0)

    contains

    function maprod(X, Y) result(Z)
    real(RP), intent(in) :: X(:, :), Y(:, :)
    real(RP), allocatable :: Z(:, :)
    integer :: i, j, k

    if (size(X, 2) /= size(Y, 1)) then
        write (*, *) "Wrong size"
        stop
    end if

    allocate (Z(size(X, 1), size(Y, 2)))
    Z = 0.0_RP
    do j = 1, size(Y, 2)
        do i = 1, size(X, 1)
            do k = 1, size(X, 2)
                Z(i, j) = Z(i, j) + X(i, k) * Y(k, j)
            end do
        end do
    end do
    end function maprod

    end module maprod_mod

    program test_matmul
    use, non_intrinsic :: maprod_mod, only : maprod, RP
    implicit none
    integer, parameter :: n = 7000
    real(RP), allocatable :: A(:, :), B(:, :)
    real :: start, finish
    integer i, j, flag

    write (*, *) 'Initialize'
    allocate (A(n, n), B(n, n))
    A = 1.0_RP
    flag = 0

    write (*, *) 'MATMUL'
    call cpu_time(start)
    do i = 1,n
        do j = 1,n
            if(A(I,J) .ne. 0.0_RP) then
                flag = 1
            end if
        end do
    end do
    if(flag == 0) then
        write (*, *) 'Zeros'
    else

        B = matmul(A, A)
    end if
    call cpu_time(finish)
    write (*, *) 'Succeed'
    write (*, *) 'Time in seconds:', finish - start  ! The use of `cpu_time` is questionable. Just ignore it.

    ! Uncomment the following code if you would like to compare `matmul` and `maprod`.
    !call cpu_time(start)
    !B = maprod(A, A)
    !call cpu_time(finish)
    !write (*, *) 'Succeed'
    !write (*, *) 'Time in seconds:', finish - start

    end program test_matmul&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="image_2022-08-04_163448948.png" style="width: 720px;"&gt;&lt;img src="https://community.intel.com/t5/image/serverpage/image-id/32332iAC083362284D6F2E/image-size/large/is-moderation-mode/true?v=v2&amp;amp;px=999&amp;amp;whitelist-exif-data=Orientation%2CResolution%2COriginalDefaultFinalSize%2CCopyright" role="button" title="image_2022-08-04_163448948.png" alt="image_2022-08-04_163448948.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="image_2022-08-04_163556102.png" style="width: 523px;"&gt;&lt;img src="https://community.intel.com/t5/image/serverpage/image-id/32333i7BBE5274C44D4B86/image-size/large/is-moderation-mode/true?v=v2&amp;amp;px=999&amp;amp;whitelist-exif-data=Orientation%2CResolution%2COriginalDefaultFinalSize%2CCopyright" role="button" title="image_2022-08-04_163556102.png" alt="image_2022-08-04_163556102.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;A linear regression on the second chart yields residuals that are interesting.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="image_2022-08-04_163734445.png" style="width: 999px;"&gt;&lt;img src="https://community.intel.com/t5/image/serverpage/image-id/32334iBA51EEBA59369588/image-size/large/is-moderation-mode/true?v=v2&amp;amp;px=999&amp;amp;whitelist-exif-data=Orientation%2CResolution%2COriginalDefaultFinalSize%2CCopyright" role="button" title="image_2022-08-04_163734445.png" alt="image_2022-08-04_163734445.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;An algorithm that is O(n*n*n) is not optimal based on current publications.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Also if you search for any zero columns or rows, you should be able to reduce the run time.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Somewhere between 7000 and 10000 you hit a VM limit.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I changed the program so all the values are 1 and added in a check for all zeros on the matrix, which runs in 0.1 seconds.&amp;nbsp;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Thu, 04 Aug 2022 21:42:23 GMT</pubDate>
    <dc:creator>JohnNichols</dc:creator>
    <dc:date>2022-08-04T21:42:23Z</dc:date>
    <item>
      <title>MATMUL</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/MATMUL/m-p/1406127#M162315</link>
      <description>&lt;P&gt;On the Fortran discourse site, there has been a discussion about matmul. The notes include a comparison of the results for different compilers and machines.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Running the program on IFORT in 32 bit mode, (no idea why 64 bit mode was slower). On a DELL Precision 5570 - Core I7 - 11850H with 32GB memory and a Samsung M2 drive, I get the analysis times shown on the graphs. The first graph is the run time as documented in the program and the second is the cubic root of the run time.&amp;nbsp; A linear regression shows the time starts to climb above cubic past 6000 by a little bit.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;No other programs running.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="fortran"&gt;module maprod_mod
    implicit none
    private
    public :: maprod, RP
    integer, parameter :: RP = kind(0.0D0)

    contains

    function maprod(X, Y) result(Z)
    real(RP), intent(in) :: X(:, :), Y(:, :)
    real(RP), allocatable :: Z(:, :)
    integer :: i, j, k

    if (size(X, 2) /= size(Y, 1)) then
        write (*, *) "Wrong size"
        stop
    end if

    allocate (Z(size(X, 1), size(Y, 2)))
    Z = 0.0_RP
    do j = 1, size(Y, 2)
        do i = 1, size(X, 1)
            do k = 1, size(X, 2)
                Z(i, j) = Z(i, j) + X(i, k) * Y(k, j)
            end do
        end do
    end do
    end function maprod

    end module maprod_mod

    program test_matmul
    use, non_intrinsic :: maprod_mod, only : maprod, RP
    implicit none
    integer, parameter :: n = 7000
    real(RP), allocatable :: A(:, :), B(:, :)
    real :: start, finish
    integer i, j, flag

    write (*, *) 'Initialize'
    allocate (A(n, n), B(n, n))
    A = 1.0_RP
    flag = 0

    write (*, *) 'MATMUL'
    call cpu_time(start)
    do i = 1,n
        do j = 1,n
            if(A(I,J) .ne. 0.0_RP) then
                flag = 1
            end if
        end do
    end do
    if(flag == 0) then
        write (*, *) 'Zeros'
    else

        B = matmul(A, A)
    end if
    call cpu_time(finish)
    write (*, *) 'Succeed'
    write (*, *) 'Time in seconds:', finish - start  ! The use of `cpu_time` is questionable. Just ignore it.

    ! Uncomment the following code if you would like to compare `matmul` and `maprod`.
    !call cpu_time(start)
    !B = maprod(A, A)
    !call cpu_time(finish)
    !write (*, *) 'Succeed'
    !write (*, *) 'Time in seconds:', finish - start

    end program test_matmul&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="image_2022-08-04_163448948.png" style="width: 720px;"&gt;&lt;img src="https://community.intel.com/t5/image/serverpage/image-id/32332iAC083362284D6F2E/image-size/large/is-moderation-mode/true?v=v2&amp;amp;px=999&amp;amp;whitelist-exif-data=Orientation%2CResolution%2COriginalDefaultFinalSize%2CCopyright" role="button" title="image_2022-08-04_163448948.png" alt="image_2022-08-04_163448948.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="image_2022-08-04_163556102.png" style="width: 523px;"&gt;&lt;img src="https://community.intel.com/t5/image/serverpage/image-id/32333i7BBE5274C44D4B86/image-size/large/is-moderation-mode/true?v=v2&amp;amp;px=999&amp;amp;whitelist-exif-data=Orientation%2CResolution%2COriginalDefaultFinalSize%2CCopyright" role="button" title="image_2022-08-04_163556102.png" alt="image_2022-08-04_163556102.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;A linear regression on the second chart yields residuals that are interesting.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="image_2022-08-04_163734445.png" style="width: 999px;"&gt;&lt;img src="https://community.intel.com/t5/image/serverpage/image-id/32334iBA51EEBA59369588/image-size/large/is-moderation-mode/true?v=v2&amp;amp;px=999&amp;amp;whitelist-exif-data=Orientation%2CResolution%2COriginalDefaultFinalSize%2CCopyright" role="button" title="image_2022-08-04_163734445.png" alt="image_2022-08-04_163734445.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;An algorithm that is O(n*n*n) is not optimal based on current publications.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Also if you search for any zero columns or rows, you should be able to reduce the run time.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Somewhere between 7000 and 10000 you hit a VM limit.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I changed the program so all the values are 1 and added in a check for all zeros on the matrix, which runs in 0.1 seconds.&amp;nbsp;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 04 Aug 2022 21:42:23 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/MATMUL/m-p/1406127#M162315</guid>
      <dc:creator>JohnNichols</dc:creator>
      <dc:date>2022-08-04T21:42:23Z</dc:date>
    </item>
    <item>
      <title>Re: MATMUL</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/MATMUL/m-p/1406334#M162321</link>
      <description>&lt;P&gt;As Dr Fortran has noted, there are broken links on the Intel website.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A title="GEMM" href="https://www.intel.com/content/www/us/en/develop/documentation/mkl-tutorial-c/top/multiplying-matrices-using-dgemm.html" target="_self"&gt;https://www.intel.com/content/www/us/en/develop/documentation/mkl-tutorial-c/top/multiplying-matrices-using-dgemm.html&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The links point to generic pages, not the actual contents listed, some of those pages have 50 other links, and by the time you scan through you are lost.&amp;nbsp; &amp;nbsp;The links point to pretty simple things you should not have to then hunt for on your website.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Sample Picture of broken link - all do not work properly.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="image_2022-08-05_092705010.png" style="width: 746px;"&gt;&lt;img src="https://community.intel.com/t5/image/serverpage/image-id/32361i9070E0C6BD67E19C/image-size/large/is-moderation-mode/true?v=v2&amp;amp;px=999&amp;amp;whitelist-exif-data=Orientation%2CResolution%2COriginalDefaultFinalSize%2CCopyright" role="button" title="image_2022-08-05_092705010.png" alt="image_2022-08-05_092705010.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 05 Aug 2022 14:28:09 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/MATMUL/m-p/1406334#M162321</guid>
      <dc:creator>JohnNichols</dc:creator>
      <dc:date>2022-08-05T14:28:09Z</dc:date>
    </item>
    <item>
      <title>Re: MATMUL</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/MATMUL/m-p/1406480#M162329</link>
      <description>&lt;P&gt;John,&lt;/P&gt;
&lt;P&gt;I would be interested if you could provide your statistics using a preferred DO order.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="fortran"&gt;! I do not like the DO order in this example
    do j = 1, size(Y, 2)
        do i = 1, size(X, 1)
            do k = 1, size(X, 2)
                Z(i, j) = Z(i, j) + X(i, k) * Y(k, j)
            end do
        end do
    end do

!  an improvement for memory access is
    do j = 1, size(Y, 2)
        do k = 1, size(X, 2)
            do i = 1, size(X, 1)
                Z(i, j) = Z(i, j) + X(i, k) * Y(k, j)
            end do
        end do
    end do

!  which using array syntax can become 
    do j = 1, size(Y, 2)
        do k = 1, size(X, 2)
            Z(:, j) = Z(:, j) + X(:, k) * Y(k, j)
        end do
    end do
&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This DO order is also suitable for !$OMP for larger examples&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I have now included an adaption to the original post that tests different approaches for DO order, partitioning and OpenMP to improve L1 and L3 cache usage and SIMD instructions. These are only partly successful, so a start to identify some problems that remain.&lt;/P&gt;
&lt;P&gt;Perhaps others can identify better approaches for improving efficiency for larger memory problems.&lt;/P&gt;
&lt;P&gt;It is important to differentiate the cache inefficiency, that occurrs with larger n, from the O(n^3) op count.&lt;/P&gt;</description>
      <pubDate>Sun, 07 Aug 2022 09:01:23 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/MATMUL/m-p/1406480#M162329</guid>
      <dc:creator>John_Campbell</dc:creator>
      <dc:date>2022-08-07T09:01:23Z</dc:date>
    </item>
    <item>
      <title>Re: MATMUL</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/MATMUL/m-p/1406977#M162362</link>
      <description>&lt;P&gt;An enhanced version with extra OpenMP test.&lt;/P&gt;</description>
      <pubDate>Tue, 09 Aug 2022 04:56:18 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/MATMUL/m-p/1406977#M162362</guid>
      <dc:creator>John_Campbell</dc:creator>
      <dc:date>2022-08-09T04:56:18Z</dc:date>
    </item>
    <item>
      <title>Re: MATMUL</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/MATMUL/m-p/1407093#M162364</link>
      <description>&lt;P&gt;Sorry a bit busy.&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 09 Aug 2022 13:09:42 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/MATMUL/m-p/1407093#M162364</guid>
      <dc:creator>JohnNichols</dc:creator>
      <dc:date>2022-08-09T13:09:42Z</dc:date>
    </item>
  </channel>
</rss>

