ユーザー定義の移行規則#

インテル® DPC++ 互換性ツールは、移行規則を適用して CUDA コードを SYCL* コードに移行します。このツールで使用する移行規則には 3 つのカテゴリーがあります。

  • デフォルトの移行規則。インテル® DPC++ 互換性ツールの移行で使用されるビルトインの移行規則。

  • 事前定義されたオプションの移行規則。必要に応じて利用できる事前定義された移行規則のセット。利用可能な事前定義された移行規則は、インテル® DPC++ 互換性ツールのインストール・パスの extensions/opt_rules フォルダーにあります。

  • ユーザー定義の移行規則。ユーザーが定義したカスタム移行規則。ユーザー定義の移行規則は、インテル® DPC++ 互換性ツールの移行機能を拡張して、特定の CUDA* 構文から SYCL* 構文への移行をターゲットにできます。

移行規則ファイルを指定#

移行に使用する事前定義またはユーザー定義の移行規則ファイルを指定するには、コマンドラインで -rule-file オプションを使用します。

1 つのコマンドで -rule-file オプションを複数回指定することで、複数の異なる移行規則ファイルを指定できます。以下に例を示します。

dpct sample.cu --rule-file=rule_file1.YAML --rule-file=rule_file2.YAML

詳細については、「コマンドライン・オプションのリファレンス」を参照してください。

ユーザー定義の移行規則を記述#

移行規則は YAML ファイルで指定されます。1 つの規則ファイルに複数の移行規則を含めることができます。規則を定義するには、次の <キー>:<値> を使用します。

キー

説明

Rule

文字列

必須です。規則の一意な名前を指定します。

Priority

Takeover | Default | Fallback

必須です。規則の優先度を指定します。Takeover > Default > Fallback。規則が競合する場合、優先度の高い規則が優先されます。

Kind

Macro | API | Header | Type | Class | Enum

必須です。規則のタイプを指定します。

In

文字列

必須です。入力ソースコード内のターゲット名を指定します。

Out

文字列

必須です。出力ソースコード内の最終的な形式を指定します。

Includes

ヘッダーファイルのリスト

必須です。出力ソースコードでインクルードするヘッダーファイルを指定します。値には空のリストを指定することもできます。

EnumName

文字列

Enum 規則タイプの enum 名を指定します。

Fields

文字列

クラス規則タイプのフィールドの移行規則を指定します。

Methods

文字列

クラス規則タイプのメソッドの移行規則を指定します。

Prefix

文字列

ヘッダー規則タイプのプリフィクスを指定します。
例: #ifdef ...

Postfix

文字列

ヘッダー規則タイプのポストフックスを指定します。
例: #endif ...

例えば、次のユーザー定義の移行規則ファイルは、さまざまな規則タイプを示しています。それぞれの規則の動作は、対応するコメントで説明されています。

---                                                    # [YAML syntax] Begin the document
- Rule: rule_forceinline                               # Rule to migrate "__forceinline__" to "inline"
  Kind: Macro                                          # Rule type
  Priority: Takeover                                   # Rule priority
  In: __forceinline__                                  # Target macro name in the input source code
  Out: inline                                          # Migrated name of the macro in the output source code
  Includes: ["header1.h", "\"header2.h\""]             # List of header file names which the new macro depends on
- Rule: rule_foo                                       # Rule to migrate "foo(a,b)" to "int *new_ptr=bar(*b)"
  Kind: API
  Priority: Takeover
  In: foo                                              # Target function name in the input source code
  Out: $type_name_of($2) *new_ptr = bar($deref($1))    # Format of the migrated result in the output source code
  Includes: ["<header3>"]
- Rule: rule_cmath                                     # Rule to migrate "include<cmath>" to "#include<mymath>"
  Kind: Header
  Priority: Takeover
  In: cmath
  Out: mymath
  Prefix: "#ifdef USE_MYMATH\n"                        # Add prefix before "#include<mymath>"
  Postfix: "#endif\n"                                  # Add postfix after "#include<mymath>"
  Includes: [""]
- Rule: rule_classA                                    # Rule to migrate "classA" to "classB"
  Kind: Class
  Priority: Takeover
  In: classA
  Out: classB
  Includes: []
  Fields:                                              # Specify the migration rule of fields of classA
    - In: fieldA                                       # Migrate classA.fieldA to getter and setter
      OutGetter: get_a                                 # Migrate value reference of classA.fieldA to classB.get_a()
      OutSetter: set_a                                 # Migrate value assignment of classA.fieldA to classB.set_a()
    - In: fieldC
      Out: fieldD                                      # Migrate classA.fieldC to classB.fieldD
  Methods:
    - In: methodA
      Out: a.methodB($2)                               # Migrate classA.methodA(x,y) to a.methodB(y)
- Rule: rule_Fruit                                     # Rule to migrate "Fruit:apple" to "Fruit:pineapple"
  Kind: Enum
  Priority: Takeover
  EnumName: Fruit
  In: apple
  Out: pineapple
  Includes: ["fruit.h"]
- Rule: type_rule                                      # Migrate "OldType" to "NewType"
  Kind: Type
  Priority: Takeover
  In: OldType
  Out: NewType
  Includes: []

...                                                    # [YAML syntax] End the document

ユーザー定義の API 移行規則の出力キーの文法#

Kind: API の移行規則で Out キーの値のフォーマットを記述するには、次のバッカス・ナウア記法を使用します。

OutValue::= Token | Token OutValue # OutValue is the value for the "out" key 
Token::= AnyString | Keyword # AnyString is a string provided by the user 
Keyword::= ArgIndex
   | $queue                              # Represents the queue string
   | $context                            # Represents the context string
   | $device                             # Represents the device string
   | $deref(ArgIndex)                    # The dereferenced value of the argument
   | $type_name_of(ArgIndex)             # The type name of the argument
   | $deref_type(ArgIndex)               # The dereferenced type name of the argument
   | $addr_of(ArgIndex)                  # The address of the argument
ArgIndex::= $Int                         # Int should be a greater than zero integer

次のシナリオでは、この文法を使用してコードを移行するユーザー定義の移行規則をツールがどのように使用するか説明します。

次のユーザー定義の API 移行規則について考えます。

- Rule: rule_foo 
  Kind: API 
  Priority: Takeover 
  In: foo 
  Out: $type_name_of($2) new_ptr = bar($deref($1), $3) 
  Includes: ["<header3>"]

入力ソースコードに規則に一致する関数呼び出しが含まれている場合、ツールは InOut キーの値を解析し、入力ソースコードと出力ソースコード間のキーワードマッピングを記述します。例えば、入力ソースコードでは、次のように使用します。

int *ptr, *ptr2; 
foo(ptr, ptr2, 30);

このツールは次のマッピングを提供します。

キーワード

入力ソースコードの一致

移行結果

$1

ptr

ptr

$2

ptr2

ptr2

$3

30

30

$type_name_of($2)

N/A

int*

$deref($1)

N/A

*ptr

このマッピングにより、ツールは入力ソースコードを次の出力ソースコードに移行します。

int *ptr, *ptr2; 
int * new_ptr = bar(*ptr, 30);