コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2020年7月14日 >>> 2020年7月14日
link もっと後

2020年7月14日

OpenCLとICD

目次: OpenCL

OpenCLは複数のベンダーのデバイスを同時に扱うことができます。ICD(Installable Client Driver)というそうです。ICDはGPUなどのデバイスを制御し、アプリケーションとICDの間にICDローダーが存在します。


アプリケーション、ICDローダー、ICDの関係


Debianでのライブラリ名

Debian TestingではICDローダーとしてocl-icd-2.2.12が使われています。

Debian TestingのICD loader
$ apt-cache search ocl-icd-libopencl1

ocl-icd-libopencl1 - Generic OpenCL ICD Loader

ローダーのソースコードはGitHub(リンク)にあります。

先程、図示したもの以外にもICDはいくつか実装があります。現時点のDebian Testingでは下記が提供されていました。

  • pocl-opencl-icd: 主にCPU向け
  • beignet-opencl-icd: 比較的古いIntel GPU向け
  • intel-opencl-icd: 比較的新しいIntel GPU向け、Testingにしか存在しない
  • mesa-opencl-icd: AMD GPU向け
  • nvidia-opencl-icd: nVidia GPU向け、ソースコードは公開されていない

IntelはICDのソースコードを完全にオープンにしています。NVIDIAは公開していません。AMDもないのかな?

ICDのロード手順

動作を追ってみたいと思います。アプリケーションにはclinfoを使います。ocl-icdは環境変数OCL_ICD_DEBUG=15に設定すると、動作時に詳細なログを出力します。デバッガで追うのと併用するとわかりやすいです。

  • clinfo: clGetPlatformIDs() を呼ぶ
  • ocl-icd: _initClIcd() -> _initClIcd_real() -> __initClIcd()
  • ocl-icd: _find_num_icds(): /etc/OpenCL/vendorsの *.icdファイルを見る(*.soへのパスが書いてある)
  • ocl-icd: _load_icd(): *.soをdlopen()
  • ocl-icd: _find_and_check_platforms(): 後述

ローダーが走査するディレクトリは /etc/OpenCL/vendorsがハードコードされていますが、環境変数OPENCL_VENDOR_PATHで変更できます。

ICDのロードの中心となる処理は _find_and_check_platforms() です。

  • dlsym() でclGetExtensionFunctionAddress() のアドレスを得る
  • clGetExtensionFunctionAddress() でclIcdGetPlatformIDsKHR() のアドレスを得る
  • clGetExtensionFunctionAddress() でclGetPlatformInfo() のアドレスを得る
  • clIcdGetPlatformIDsKHR() でプラットフォーム数とプラットフォームの情報を得る

プラットフォームは説明が難しいですが、OpenCL APIの実体+任意のドライバ固有のデータとでも言いましょうか。変数の型はcl_platform_id * 型です。cl_platform_idは少なくとも先頭のメンバはstruct _cl_icd_dispatch *dispatchでなければなりません。dispatchの後ろには他の情報が入っていても問題ないようです。

cl_platform_idとdispatch

// ocl-icd/ocl_icd_loader.c

static inline void _find_and_check_platforms(cl_uint num_icds) {
  cl_uint i;

...

    cl_platform_id *platforms = (cl_platform_id *) malloc( sizeof(cl_platform_id) * num_platforms);
    error = (*plt_fn_ptr)(num_platforms, platforms, NULL);

...

    for(j=0; j<num_platforms; j++) {
      debug(D_LOG, "Checking platform %i", j);
      struct platform_icd *p=&_picds[_num_picds];
      char *param_value=NULL;
      p->extension_suffix=NULL;
      p->vicd=&_icds[i];
      p->pid=platforms[j];    //★★pid = platform IDのことらしい

      /* If clGetPlatformInfo is not exported and we are here, it
       * means that OCL_ICD_ASSUME_ICD_EXTENSION. Si we try to take it
       * from the dispatch * table. If that fails too, we have to
       * bail.
       */
      if (plt_info_ptr == NULL) {
        plt_info_ptr = p->pid->dispatch->clGetPlatformInfo;    //★★dispatchメンバが存在することを前提としている

      
// ocl-icd/khronos-headers/CL/cl.h

typedef struct _cl_platform_id *    cl_platform_id;


// ocl-icd/(build-dir)/ocl_icd_loader_gen.h

struct _cl_platform_id { struct _cl_icd_dispatch *dispatch; };    //★★dispatch以外は特に規定がなさそう


// ocl-icd/(build-dir)/ocl_icd.h

struct _cl_icd_dispatch {
#ifdef CL_VERSION_1_0
  CL_API_ENTRY cl_int (CL_API_CALL*clGetPlatformIDs)(
    cl_uint          /* num_entries */,
    cl_platform_id * /* platforms */,
    cl_uint *        /* num_platforms */
  ) CL_API_SUFFIX__VERSION_1_0;
#else
  CL_API_ENTRY cl_int (CL_API_CALL* clUnknown0)(void);
#endif

#ifdef CL_VERSION_1_0
  CL_API_ENTRY cl_int (CL_API_CALL*
  clGetPlatformInfo)(
    cl_platform_id   /* platform */,
    cl_platform_info /* param_name */,
    size_t           /* param_value_size */,
    void *           /* param_value */,
    size_t *         /* param_value_size_ret */
  ) CL_API_SUFFIX__VERSION_1_0;
#else
  CL_API_ENTRY cl_int (CL_API_CALL* clUnknown1)(void);
#endif

...

//★★こんな調子で関数ポインタの定義が延々と続く

先頭のdispatchはたくさんの関数ポインタが並んだ巨大な構造体です。アプリケーションから見るとOpenCLのAPIはocl-icdが提供しているように見えますが、ocl-icdのAPI実装はdispatchの関数ポインタを呼ぶラッパー関数であり、関数ポインタと、OpenCL API実装の本体を提供するのは各ICDの役割です。

編集者:すずき(2023/09/24 11:57)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
2020年7月14日 >>> 2020年7月14日
link もっと後

管理用メニュー

link 記事を新規作成

<2020>
<<<07>>>
---1234
567891011
12131415161718
19202122232425
262728293031-

最近のコメント5件

  • link 24年4月22日
    hdkさん (04/24 08:36)
    「うちのHHFZ4310は15年突破しまし...」
  • link 24年4月22日
    すずきさん (04/24 00:37)
    「ちゃんと数えてないですけど蛍光管が10年...」
  • link 24年4月22日
    hdkさん (04/23 20:52)
    「おお... うちのHHFZ4310より後...」
  • link 20年6月19日
    すずきさん (04/06 22:54)
    「ディレクトリを予め作成しておけば良いです...」
  • link 20年6月19日
    斎藤さん (04/06 16:25)
    「「Preferencesというメニューか...」

最近の記事3件

  • link 24年2月7日
    すずき (04/24 02:52)
    「[複数の音声ファイルのラウドネスを統一したい] PCやデジタル音楽プレーヤーで音楽を聞いていると、曲によって音量の大小が激しく...」
  • link 24年4月22日
    すずき (04/23 20:13)
    「[仕事部屋の照明が壊れた] いきなり仕事部屋のシーリングライトが消えました。蛍光管の寿命にしては去年(2022年10月19日の...」
  • link 24年4月17日
    すずき (04/18 22:44)
    「[VSCodeとMarkdownとPlantUMLのローカルサーバー] 目次: LinuxVSCodeのPlantUML Ex...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 04/24 08:36