バックグラウンド
新しいGCC 5.1リリースを使用して、OpenMP ブロックを Intel MIC (つまり、Xeon Phi) にオフロードしようとしましたが、うまくいきませんでした。GCCオフロードページに続いて、"intelmic" およびホスト コンパイラ用の "accel" ターゲット コンパイラをビルドするスクリプトをまとめましたbuild.sh。コンパイルは正常に完了したようです。
次に、スクリプトを使用して、以下にリストされている単純なプログラムenv.shをコンパイルしようとします。hello.cただし、このプログラムはホスト上でのみ実行され、ターゲット デバイスでは実行されないようです。
GCC のコンパイルだけでなく、一般的なオフロードにも慣れていないため、間違っている可能性があることが複数あります。ただし、既に言及されているリソースに加えて、次のことを調査しました (リンクを投稿するのに十分な担当者がいません)。
- Xeon Phi のオフロード
- Xeon Phi チュートリアル
- インテル Xeon Phi オフロード プログラミング モデル
最大の問題は、通常 Intel コンパイラを参照していることです。コピーを購入する予定ですが、現在コピーはありません。さらに、開発パイプラインの大部分はすでに GCC と統合されており、(可能であれば) その状態を維持したいと考えています。
最新の MPSS 3.5 ディストリビューションをインストールし、Ubuntu で動作するように必要な変更を加えました。システム内の Xeon Phis のステータスを正常に通信して確認できます。
私たちの努力では、コードがマイク エミュレーション モードで実行されている兆候も見られませんでした。
質問
- 実際に Xeon Phi にオフロードするホスト/ターゲット GCC コンパイラの組み合わせを構築した人はいますか? もしそうなら、どのリソースを使用しましたか?
- ビルド スクリプトに欠けているものはありますか?
- テストソースコードに問題はありますか? それらはエラーなしでコンパイルされ (以下で説明するものを除く)、48 スレッド (つまり、ホスト システムの論理スレッドの数) で実行されます。
- Google 検索ではあまり情報が得られないため、次のステップについて提案がある人はいますか (GCC オフロードをあきらめること以外に)。これはバグですか?
ありがとう!
build.sh
#!/usr/bin/env bash
set -e -x
unset LIBRARY_PATH
GCC_DIST=$PWD/gcc-5.1.0
# Modify these to control where the compilers are installed
TARGET_PREFIX=$HOME/gcc
HOST_PREFIX=$HOME/gcc
TARGET_BUILD=/tmp/gcc-build-mic
HOST_BUILD=/tmp/gcc-build-host
# i dropped the emul since we are not planning to emulate!
TARGET=x86_64-intelmic-linux-gnu
# should this be a quad (i.e. pc)?? default (Ubuntu) build seems to be x86_64-linux-gnu
HOST=x86_64-pc-linux-gnu
# check for the GCC distribution
if [ ! -d $GCC_DIST ]; then
echo "gcc-5.1.0 distribution should be here $PWD"
exit 0
fi
#sudo apt-get install -y libmpfr-dev libgmp-dev libmpc-dev libisl-dev dejagnu autogen sysvbanner
# prepare and configure the target compiler
mkdir -p $TARGET_BUILD
pushd $TARGET_BUILD
$GCC_DIST/configure \
--prefix=$TARGET_PREFIX \
--enable-languages=c,c++,fortran,lto \
--enable-liboffloadmic=target \
--disable-multilib \
--build=$TARGET \
--host=$TARGET \
--target=$TARGET \
--enable-as-accelerator-for=$HOST \
--program-prefix="${TARGET}-"
#--program-prefix="$HOST-accel-$TARGET-" \
# try adding the program prefix as HINTED in the https://gcc.gnu.org/wiki/Offloading
# do we need to specify a sysroot??? Wiki says we don't need one... but it also says "better to configure as cross compiler....
# build and install
make -j48 && make install
popd
# prepare and build the host compiler
mkdir -p $HOST_BUILD
pushd $HOST_BUILD
$GCC_DIST/configure \
--prefix=$HOST_PREFIX \
--enable-languages=c,c++,fortran,lto \
--enable-liboffloadmic=host \
--disable-multilib \
--build=$HOST \
--host=$HOST \
--target=$HOST \
--enable-offload-targets=$TARGET=$TARGET_PREFIX
make -j48 && make install
popd
env.sh
#!/usr/bin/env bash
TARGET_PREFIX=$HOME/gcc
HOST_PREFIX=$HOME/gcc
HOST=x86_64-pc-linux-gnu
VERSION=5.1.0
export LD_LIBRARY_PATH=/opt/intel/mic/coi/host-linux-release/lib:/opt/mpss/3.4.3/sysroots/k1om-mpss-linux/usr/lib64:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$HOST_PREFIX/lib:$HOST_PREFIX/lib64:$HOST_PREFIX/lib/gcc/$HOST/$VERSION:$LD_LIBRARY_PATH
export PATH=$HOST_PREFIX/bin:$PATH
hello.c (バージョン 1)
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
int nthreads, tid;
/* Fork a team of threads giving them their own copies of variables */
#pragma offload target (mic)
{
#pragma omp parallel private(nthreads,tid)
{
/* Obtain thread number */
tid = omp_get_thread_num();
printf("Hello World from thread = %d\n", tid);
/* Only master thread does this */
if (tid == 0) {
nthreads = omp_get_num_threads();
printf("Number of threads = %d\n", nthreads);
}
#ifdef __MIC__
printf("on target...\n");
#else
printf("on host...\n");
#endif
}
}
}
このコードを次のようにコンパイルしました。
gcc -fopenmp -foffload=x86_64-intelmic-linux-gnu hello.c -o hello
hello_omp.c (バージョン 2)
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
int nthreads, tid;
/* Fork a team of threads giving them their own copies of variables */
#pragma omp target device(mic)
{
#pragma omp parallel private(nthreads,tid)
{
/* Obtain thread number */
tid = omp_get_thread_num();
printf("Hello World from thread = %d\n", tid);
/* Only master thread does this */
if (tid == 0) {
nthreads = omp_get_num_threads();
printf("Number of threads = %d\n", nthreads);
}
#ifdef __MIC__
printf("on target...\n");
#else
printf("on host...\n");
#endif
}
}
}
ほとんど同じことですが、代わりに
#pragma omp target device
構文。実際、micでは問題が発生しますが、任意のデバイス番号 (つまり 0) を使用すると、ホスト上でコンパイルおよび実行されます。このコードは、同じ方法でコンパイルされました。