チュートリアル: インテル® MKL 2018 を使用した行列乗算 (C 言語)

dgemm を使用した行列の乗算

インテル® MKL には、行列乗算用のルーチンが用意されています。最も広く利用されるのは、倍精度行列の積を計算する dgemm ルーチンです。

dgemm ルーチンは、いくつかの計算を実行できます。例えば、このルーチンを使用して、AB の転置または共役転置を実行することができます。dgemm ルーチンの機能の詳細とすべての引数については、『インテル® MKL デベロッパー・リファレンス』のcblas_?gemm (英語) を参照してください。

行列乗算に dgemm を使用する

この演習は、変数を宣言し、行列値を配列で格納した後、dgemm を呼び出して行列の積を計算します。これらの行列の格納には配列を使用します。

演習の 1 次元配列は、配列の連続するセルに各列の要素を配置して、行列を格納します。

このチュートリアルの演習の C ソースコードは、https://software.intel.com/en-us/product-code-samples (英語) からダウンロードできます。

/* C ソースコードは dgemm_example.c を参照 */

#define min(x,y) (((x) < (y)) ?  (x) : (y))

#include <stdio.h>
#include <stdlib.h>
#include "mkl.h"

int main()
{
    double *A, *B, *C;
    int m, n, k, i, j;
    double alpha, beta;

    printf ("\n This example computes real matrix C=alpha*A*B+beta*C using \n"
            " Intel® MKL function dgemm, where A, B, and  C are matrices and \n"
            " alpha and beta are double precision scalars\n\n");

    m = 2000, k = 200, n = 1000;
    printf (" Initializing data for matrix multiplication C=A*B for matrix \n"
            " A(%ix%i) and matrix B(%ix%i)\n\n", m, k, k, n);
    alpha = 1.0; beta = 0.0;

    printf (" Allocating memory for matrices aligned on 64-byte boundary for better \n"
            " performance \n\n");
    A = (double *)mkl_malloc( m*k*sizeof( double ), 64 );
    B = (double *)mkl_malloc( k*n*sizeof( double ), 64 );
    C = (double *)mkl_malloc( m*n*sizeof( double ), 64 );
    if (A == NULL || B == NULL || C == NULL) {
      printf( "\n ERROR: Can't allocate memory for matrices.   Aborting...\n\n");
      mkl_free(A);
      mkl_free(B);
      mkl_free(C);
      return 1;
    }

    printf (" Intializing matrix data \n\n");
    for (i = 0; i < (m*k); i++) {
        A[i] = (double)(i+1);
    }

    for (i = 0; i < (k*n); i++) {
        B[i] = (double)(-i-1);
    }

    for (i = 0; i < (m*n); i++) {
        C[i] = 0.0;
    }

    printf (" Computing matrix product using Intel® MKL dgemm function via CBLAS interface \n\n");
    cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, 
                m, n, k, alpha, A, k, B, n, beta, C, n);
    printf ("\n Computations completed.\n\n");

    printf (" Top left corner of matrix A: \n");
    for (i=0; i<min(m,6); i++) {
      for (j=0; j<min(k,6); j++) {
        printf ("%12.0f", A[j+i*k]);
      }
      printf ("\n");
    }

    printf ("\n Top left corner of matrix B: \n");
    for (i=0; i<min(k,6); i++) {
      for (j=0; j<min(n,6); j++) {
        printf ("%12.0f", B[j+i*n]);
      }
      printf ("\n");
    }
    
    printf ("\n Top left corner of matrix C: \n");
    for (i=0; i<min(m,6); i++) {
      for (j=0; j<min(n,6); j++) {
        printf ("%12.5G", C[j+i*n]);
      }
      printf ("\n");
    }

    printf ("\n Deallocating memory \n\n");
    mkl_free(A);
    mkl_free(B);
    mkl_free(C);

    printf (" Example completed.\n\n");
    return 0;
}

この演習は、dgemm ルーチンの呼び出し方法を説明します。実際のアプリケーションでは、行列乗算の結果を使用します。

この dgemm ルーチンの呼び出しは、行列の乗算を行います。

cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
           m, n, k, alpha, A, k, B, n, beta, C, n);

引数は、インテル® MKL がどのように演算を行うかを指定するオプションです。ここでは、以下の引数が指定されています。

CblasRowMajor

行列が行優先で格納され、行列の各行の要素が上記の図で示されているように連続して格納されることを示します。

CblasNoTrans

行列 AB を乗算前に転置または共役転置しないことを示す列挙型。

m、n、k

行列のサイズを示す整数:

  • A: mk

  • B: kn

  • C: mn

alpha

行列 AB の積の測定に使用する実数値。

A

行列 A の格納に使用する配列。

k

配列 A のリーディング・ディメンジョン、またはメモリーの連続する列 (列優先で格納する場合) 間の要素の数。この演習では、リーディング・ディメンジョンは列の数と同じです。

B

行列 B の格納に使用する配列。

n

配列 B のリーディング・ディメンジョン、またはメモリーの連続する列 (列優先で格納する場合) 間の要素の数。この演習では、リーディング・ディメンジョンは列の数と同じです。

beta

行列 C の測定に使用する実数値。

C

行列 C の格納に使用する配列。

n

配列 C のリーディング・ディメンジョン、またはメモリーの連続する列 (列優先で格納する場合) 間の要素の数。この演習では、リーディング・ディメンジョンは列の数と同じです。

コードのコンパイルとリンク

インテル® MKL には、さまざまなコンパイラーとサードパーティーのライブラリー、およびインターフェイスと互換性のある、複数のプロセッサーとオペレーティング・システム向けにコードを生成する多くのオプションが用意されています。インテル® Parallel Studio XE Composer Edition でこの演習をコンパイルおよびリンクする場合は、以下のように入力します。

代わりに、提供されているビルドスクリプトを使用して実行ファイルをビルドおよび実行することもできます。

このチュートリアルの実行ファイルのビルドスクリプトは次のとおりです。

サンプル

実行ファイル

dgemm_example.c

run_dgemm_example

dgemm_with_timing.c

run_dgemm_with_timing

matrix_multiplication.c

run_matrix_multiplication

dgemm_threading_effect_example.c

run_dgemm_threading_effect_example

ここでは、https://software.intel.com/en-us/articles/intel-math-kernel-library-intel-mkl-2018-getting-started (英語) で説明されているように、インテル® MKL をインストールして環境変数を設定済みであることを想定しています。

ほかのコンパイラーの場合は、インテル® MKL リンクライン・アドバイザー (https://software.intel.com/en-us/articles/intel-mkl-link-line-advisor/ (英語)) を使用して、このチュートリアルの演習をコンパイルおよびリンクするコマンドラインを取得します。

コンパイルとリンクが完了したら、生成された実行ファイル dgemm_example.exe (Windows*) または a.out (Linux*/macOS*) を実行します。

最適化に関する注意事項

インテル® コンパイラーでは、インテル® マイクロプロセッサーに限定されない最適化に関して、他社製マイクロプロセッサー用に同等の最適化を行えないことがあります。これには、インテル® ストリーミング SIMD 拡張命令 2、インテル® ストリーミング SIMD 拡張命令 3、インテル® ストリーミング SIMD 拡張命令 3 補足命令などの最適化が該当します。インテルは、他社製マイクロプロセッサーに関して、いかなる最適化の利用、機能、または効果も保証いたしません。本製品のマイクロプロセッサー依存の最適化は、インテル® マイクロプロセッサーでの使用を前提としています。インテル® マイクロアーキテクチャーに限定されない最適化のなかにも、インテル® マイクロプロセッサー用のものがあります。この注意事項で言及した命令セットの詳細については、該当する製品のユーザー・リファレンス・ガイドを参照してください。

注意事項の改訂 #20110804

戻る次へ

関連情報