移行ルール#

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

  • デフォルトの移行ルール。ツールの移行で使用されるビルトインの移行ルール。

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

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

移行ルールファイルを指定#

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

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

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

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

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

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

キー

説明

規則

文字列値

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

Priority

Takeover | Default | Fallback

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

Kind

Macro | API | Header | Type | Class | Enum | DisableAPIMigration | PatternRewriter | CMakeRule

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

CmakeSyntax

文字列値

必須。移行する CMake 構文名を指定します。CMake 構文に一意の名前を使用します。

MatchMode

Partial | Full

必須。完全単語一致 (Full) または部分単語一致 (Partial) で一致モードを指定します。指定しない場合、部分一致 (Partial) モードが使用されます。

In

文字列値

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

Out

文字列値

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

Includes

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

必須。出力ソースコードでインクルードするヘッダーファイルを指定します。値には以下を指定できます。

EnumName

文字列値

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

Fields

文字列値

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

Methods

文字列値

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

Prefix

文字列値

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

Postfix

文字列値

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

Subrules

文字列値

PatternRewriter ルールタイプのサブルールを指定します。

APIRestrictCondition

制限のリスト

API の制限を指定します。

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


---                                            # [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                                  # Name of migrated 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>"] 
  APIRestrictCondition:     ArgCount: 1  # Only the overloading with 1 argument will be migrated 
- 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: [] 
- Rule: disable_rule                                  # Disable the migration of an API 
  Kind: DisableAPIMigration 
  Priority: Takeover 
  In: foo                                             # Disable the migration of foo 
  Out: "」 
  Includes: [] 
- Rule: post_migration_rewriter_rule                  # Post-migration pattern rewrite rule which uses nested 
                                                      # string pattern search and replace to find and update 
                                                      # strings in the migrated code 
  Kind: PatternRewriter 
  Priority: Takeover 
  In: my_max(${args});                                # Match pattern "my_max(...);" and save the arbitrary 
                                                      # arbitrary string between "my_max(" and ");" as ${args}. 
                                                      # "args" can be a user-defined name which will be 
                                                      # referenced by "Out" and "Subrules" Out: my_min(${args}); 
                                                      # Replace the pattern string to "my_min(${args});」 
  Includes: [] 
  Subrules: 
    args:                                             # Specify the subrule to apply to ${args}, where "args」 
                                                      # is the user-defined name which is defined in "In".        
      In: a                                           # Match pattern "a" in ${args} 
      Out: b                                          # Replace the pattern string to "b" in ${args} 
...                                                   # [YAML syntax] End the document

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

Kind: API の移行ルールで Out キーの値の系s気を記述するには、次のバッカス・ナウア記法を使用します。

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);