迴圈

迴圈 - 23

版本

  • 名稱迴圈 (GitHub)

  • 網域main

  • since_version23

  • 函式False

  • 支援等級SupportType.COMMON

  • 形狀推斷True

此版本的運算子自版本 23 開始提供。

摘要

通用迴圈結構。此迴圈有多個終止條件

  1. 行程計數。在執行階段指定的迭代計數。透過指定輸入 M 來設定。選用。設定為空字串則省略。請注意,靜態行程計數 (在圖形建構時指定) 可以透過為輸入 M 傳入常數節點來指定。

  2. 迴圈終止條件。這是運算子的輸入,用於決定是否執行第一次迭代,也是主體圖形的迴圈攜帶依賴項。無論是否提供此輸入,主體圖形都必須為條件變數產生值。

此表格摘要說明此運算子的運作模式以及對等的 C 樣式程式碼

定義為 (max_trip_count, condition_var) 的運算子輸入。

  • 輸入 (“”, “”): for (int i=0; ; ++i) { cond = … // 請注意,會忽略此值,但主體中是必要值 }

  • 輸入 (“”, cond) // 請注意,這類似於 while 迴圈 bool cond = …; for (int i=0; cond; ++i) { cond = …; }

  • 輸入 (“”, 1) // 請注意,這類似於 do-while 迴圈 bool cond = true for (int i=0; cond; ++i) { cond = …; }

  • 輸入 (trip_count, “”) // 請注意,這類似於 for 迴圈 int trip_count = … for (int i=0; i < trip_count; ++i) { cond = …; // 已忽略 }

  • 輸入 (trip_count, cond) int trip_count = …; bool cond = …; for (int i=0; i < trip_count && cond; ++i) { cond = …; }

範例用法 - cond 以及行程計數

graph predict-net {
  %a = Constant[value = <Scalar Tensor [3]>]()
  %b = Constant[value = <Scalar Tensor [6]>]()
  %keepgoing = Constant[value = <Scalar Tensor [1]>]()
  %max_trip_count = Constant[value = <Scalar Tensor [10]>]()
  %keepgoing_out, %b_out, %user_defined_vals = Loop[body = <graph body-net>](%max_trip_count, %keepgoing, %b)
  return
}

graph body-net (
  %i[INT32, scalar]           // iteration number
  %keepgoing_in[BOOL, scalar] // incoming loop-termination-condition; not used
  %b_in[INT32, scalar]        // incoming value of loop-carried-dependency b
) {
  %my_local = Add(%a, %b_in)
  %b_out = Sub(%a, %b_in) // outgoing value of loop-carried-dependency b
  %keepgoing_out = Greater(%my_local, %b_out) // outgoing loop-termination-condition
  %user_defined_val = Add(%b_in, %b_in) // scan-output value to be accumulated
  return %keepgoing_out, %b_out, %user_defined_val
}

範例對等 C 程式碼

{
  /* User-defined code (enclosing scope) */
  int a = 3, b = 6;
  bool keepgoing = true; // Analogous to input cond
  /* End user-defined code */

  /* Implicitly-defined code */
  const int max_trip_count = 10; // Analogous to input M
  int user_defined_vals[]; // Imagine this is resizable
  /* End implicitly-defined code */
  /* initialize loop-carried variables and scan-output variables */
  bool keepgoing_out = keepgoing
  int b_out = b

  for (int i=0; i < max_trip_count && keepgoing_out; ++i) {
    /* Implicitly-defined code: bind actual parameter values
       to formal parameter variables of loop-body */
    bool keepgoing_in = keepgoing_out;
    bool b_in = b_out;

    /* User-defined code (loop body) */
    int my_local = a + b_in; // Reading value "a" from the enclosing scope is fine
    b_out = a - b_in;
    keepgoing_out = my_local > b_out;
    user_defined_val = b_in + b_in; // b_in and b_out are different variables
    /* End user-defined code */

    /* Implicitly defined-code */
    user_defined_vals[i] = user_defined_val // accumulate scan-output values
  }
  // int t = my_local; // Can't do this. my_local is not accessible here.

  // The values below are bound to the output variables of the loop and therefore accessible
  // b_out; user_defined_vals; keepgoing_out;
}

此程式碼片段中有幾點值得注意

  1. 來自封閉範圍 (亦即此處的變數「a」) 的值在範圍內,且可以在迴圈的輸入中參考。

  2. 迴圈主體中計算的任何需要在後續迭代中或在迴圈之後使用的值,都使用迴圈主體中的一對變數來建模,其中包含輸入變數 (例如 b_in) 和輸出變數 (例如 b_out)。這些稱為迴圈攜帶依賴項。迴圈運算節點會提供第一次迭代的輸入變數的輸入值,並傳回最終迭代產生的輸出變數的輸出值。

  3. 掃描輸出變數用於隱式串連所有迭代中計算的值。在上述範例中,所有迭代中計算的 user_defined_val 值會串連在一起,並在迴圈後傳回為 user_defined_vals 的值。

  4. 主體中建立的值無法在封閉範圍中存取,除非使用上述機制。

請注意,此運算子的語意支援「對角線」或「波前」執行。(請參閱此處的步驟 3 以取得範例:https://devblogs.nvidia.com/optimizing-recurrent-neural-networks-cudnn-5/)。前端應將多層 RNN 發射為一系列 While 運算子 (以時間作為內部迴圈維度),每個連續層會取用前一個層的 scan_outputs,並可能經過數個逐點運算子 (例如 dropout、殘差連線、線性層)。

子圖形的輸入/輸出 (由迴圈節點產生) 比對是根據順序而不是名稱。實作會根據此順序找出名稱。

屬性

  • body - GRAPH (必要)

    每次迭代執行的圖形。它有 2+N 個輸入:(iteration_num, condition, loop carried dependencies…)。它有 1+N+K 個輸出:(condition, loop carried dependencies…, scan_outputs…)。每個 scan_output 都是透過串連迴圈每次迭代結束時指定輸出值的值所建立。如果這些 scan_output 的維度或資料類型在迴圈迭代中變更,則會發生錯誤。

輸入

介於 2 到 2147483647 個輸入之間。

  • M (選用,異質) - I

    在執行階段指定的迴圈最大行程計數。選用。傳遞空字串則略過。

  • cond (選用,異質) - B

    布林終止條件。選用。傳遞空字串則略過。

  • v_initial (可變) - V

    任何迴圈攜帶依賴項的初始值 (在迴圈迭代中變更的值)

輸出

介於 1 到 2147483647 個輸出之間。

  • v_final_and_scan_outputs (可變) - V

    最後的 N 個迴圈攜帶依賴項值,然後是 K 個掃描輸出。掃描輸出必須是張量。

類型限制

  • V 的類型可以是 ( optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(complex128))), optional(seq(tensor(complex64))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(complex128)), optional(tensor(complex64)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(float4e2m1)), optional(tensor(float8e4m3fn)), optional(tensor(float8e4m3fnuz)), optional(tensor(float8e5m2)), optional(tensor(float8e5m2fnuz)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int4)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint4)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(complex128)), seq(tensor(complex64)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float4e2m1)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int4)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint4)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(complex128), tensor(complex64), tensor(double), tensor(float), tensor(float16), tensor(float4e2m1), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8) )

    所有 Tensor、Sequence(Tensor)、Optional(Tensor) 和 Optional(Sequence(Tensor)) 類型,最高支援至 IRv11 版本。

  • I 的類型是 ( tensor(int64) )

    int64 類型的張量,應為純量。

  • B 的類型是 ( tensor(bool) )

    bool 類型的張量,應為純量。

迴圈 - 21

版本

  • 名稱迴圈 (GitHub)

  • 網域main

  • since_version: 21

  • 函式False

  • 支援等級SupportType.COMMON

  • 形狀推斷True

此運算子的版本自版本 21 起可用。

摘要

通用迴圈結構。此迴圈有多個終止條件

  1. 行程計數。在執行階段指定的迭代計數。透過指定輸入 M 來設定。選用。設定為空字串則省略。請注意,靜態行程計數 (在圖形建構時指定) 可以透過為輸入 M 傳入常數節點來指定。

  2. 迴圈終止條件。這是運算子的輸入,用於決定是否執行第一次迭代,也是主體圖形的迴圈攜帶依賴項。無論是否提供此輸入,主體圖形都必須為條件變數產生值。

此表格摘要說明此運算子的運作模式以及對等的 C 樣式程式碼

定義為 (max_trip_count, condition_var) 的運算子輸入。

  • 輸入 (“”, “”): for (int i=0; ; ++i) { cond = … // 請注意,會忽略此值,但主體中是必要值 }

  • 輸入 (“”, cond) // 請注意,這類似於 while 迴圈 bool cond = …; for (int i=0; cond; ++i) { cond = …; }

  • 輸入 (“”, 1) // 請注意,這類似於 do-while 迴圈 bool cond = true for (int i=0; cond; ++i) { cond = …; }

  • 輸入 (trip_count, “”) // 請注意,這類似於 for 迴圈 int trip_count = … for (int i=0; i < trip_count; ++i) { cond = …; // 已忽略 }

  • 輸入 (trip_count, cond) int trip_count = …; bool cond = …; for (int i=0; i < trip_count && cond; ++i) { cond = …; }

範例用法 - cond 以及行程計數

graph predict-net {
  %a = Constant[value = <Scalar Tensor [3]>]()
  %b = Constant[value = <Scalar Tensor [6]>]()
  %keepgoing = Constant[value = <Scalar Tensor [1]>]()
  %max_trip_count = Constant[value = <Scalar Tensor [10]>]()
  %keepgoing_out, %b_out, %user_defined_vals = Loop[body = <graph body-net>](%max_trip_count, %keepgoing, %b)
  return
}

graph body-net (
  %i[INT32, scalar]           // iteration number
  %keepgoing_in[BOOL, scalar] // incoming loop-termination-condition; not used
  %b_in[INT32, scalar]        // incoming value of loop-carried-dependency b
) {
  %my_local = Add(%a, %b_in)
  %b_out = Sub(%a, %b_in) // outgoing value of loop-carried-dependency b
  %keepgoing_out = Greater(%my_local, %b_out) // outgoing loop-termination-condition
  %user_defined_val = Add(%b_in, %b_in) // scan-output value to be accumulated
  return %keepgoing_out, %b_out, %user_defined_val
}

範例對等 C 程式碼

{
  /* User-defined code (enclosing scope) */
  int a = 3, b = 6;
  bool keepgoing = true; // Analogous to input cond
  /* End user-defined code */

  /* Implicitly-defined code */
  const int max_trip_count = 10; // Analogous to input M
  int user_defined_vals[]; // Imagine this is resizable
  /* End implicitly-defined code */
  /* initialize loop-carried variables and scan-output variables */
  bool keepgoing_out = keepgoing
  int b_out = b

  for (int i=0; i < max_trip_count && keepgoing_out; ++i) {
    /* Implicitly-defined code: bind actual parameter values
       to formal parameter variables of loop-body */
    bool keepgoing_in = keepgoing_out;
    bool b_in = b_out;

    /* User-defined code (loop body) */
    int my_local = a + b_in; // Reading value "a" from the enclosing scope is fine
    b_out = a - b_in;
    keepgoing_out = my_local > b_out;
    user_defined_val = b_in + b_in; // b_in and b_out are different variables
    /* End user-defined code */

    /* Implicitly defined-code */
    user_defined_vals[i] = user_defined_val // accumulate scan-output values
  }
  // int t = my_local; // Can't do this. my_local is not accessible here.

  // The values below are bound to the output variables of the loop and therefore accessible
  // b_out; user_defined_vals; keepgoing_out;
}

此程式碼片段中有幾點值得注意

  1. 來自封閉範圍 (亦即此處的變數「a」) 的值在範圍內,且可以在迴圈的輸入中參考。

  2. 迴圈主體中計算的任何需要在後續迭代中或在迴圈之後使用的值,都使用迴圈主體中的一對變數來建模,其中包含輸入變數 (例如 b_in) 和輸出變數 (例如 b_out)。這些稱為迴圈攜帶依賴項。迴圈運算節點會提供第一次迭代的輸入變數的輸入值,並傳回最終迭代產生的輸出變數的輸出值。

  3. 掃描輸出變數用於隱式串連所有迭代中計算的值。在上述範例中,所有迭代中計算的 user_defined_val 值會串連在一起,並在迴圈後傳回為 user_defined_vals 的值。

  4. 主體中建立的值無法在封閉範圍中存取,除非使用上述機制。

請注意,此運算子的語意支援「對角線」或「波前」執行。(請參閱此處的步驟 3 以取得範例:https://devblogs.nvidia.com/optimizing-recurrent-neural-networks-cudnn-5/)。前端應將多層 RNN 發射為一系列 While 運算子 (以時間作為內部迴圈維度),每個連續層會取用前一個層的 scan_outputs,並可能經過數個逐點運算子 (例如 dropout、殘差連線、線性層)。

子圖形的輸入/輸出 (由迴圈節點產生) 比對是根據順序而不是名稱。實作會根據此順序找出名稱。

屬性

  • body - GRAPH (必要)

    每次迭代執行的圖形。它有 2+N 個輸入:(iteration_num, condition, loop carried dependencies…)。它有 1+N+K 個輸出:(condition, loop carried dependencies…, scan_outputs…)。每個 scan_output 都是透過串連迴圈每次迭代結束時指定輸出值的值所建立。如果這些 scan_output 的維度或資料類型在迴圈迭代中變更,則會發生錯誤。

輸入

介於 2 到 2147483647 個輸入之間。

  • M (選用,異質) - I

    在執行階段指定的迴圈最大行程計數。選用。傳遞空字串則略過。

  • cond (選用,異質) - B

    布林終止條件。選用。傳遞空字串則略過。

  • v_initial (可變) - V

    任何迴圈攜帶依賴項的初始值 (在迴圈迭代中變更的值)

輸出

介於 1 到 2147483647 個輸出之間。

  • v_final_and_scan_outputs (可變) - V

    最後的 N 個迴圈攜帶依賴項值,然後是 K 個掃描輸出。掃描輸出必須是張量。

類型限制

  • V in ( optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(complex128))), optional(seq(tensor(complex64))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(complex128)), optional(tensor(complex64)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(float8e4m3fn)), optional(tensor(float8e4m3fnuz)), optional(tensor(float8e5m2)), optional(tensor(float8e5m2fnuz)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int4)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint4)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(complex128)), seq(tensor(complex64)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int4)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint4)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(complex128), tensor(complex64), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8) )

    所有 Tensor、Sequence(Tensor)、Optional(Tensor) 和 Optional(Sequence(Tensor)) 類型,最高支援至 IRv10。

  • I 的類型是 ( tensor(int64) )

    int64 類型的張量,應為純量。

  • B 的類型是 ( tensor(bool) )

    bool 類型的張量,應為純量。

迴圈 - 19

版本

  • 名稱迴圈 (GitHub)

  • 網域main

  • since_version: 19

  • 函式False

  • 支援等級SupportType.COMMON

  • 形狀推斷True

此運算子的版本自版本 19 起可用。

摘要

通用迴圈結構。此迴圈有多個終止條件

  1. 行程計數。在執行階段指定的迭代計數。透過指定輸入 M 來設定。選用。設定為空字串則省略。請注意,靜態行程計數 (在圖形建構時指定) 可以透過為輸入 M 傳入常數節點來指定。

  2. 迴圈終止條件。這是運算子的輸入,用於決定是否執行第一次迭代,也是主體圖形的迴圈攜帶依賴項。無論是否提供此輸入,主體圖形都必須為條件變數產生值。

此表格摘要說明此運算子的運作模式以及對等的 C 樣式程式碼

定義為 (max_trip_count, condition_var) 的運算子輸入。

  • 輸入 (“”, “”): for (int i=0; ; ++i) { cond = … // 請注意,會忽略此值,但主體中是必要值 }

  • 輸入 (“”, cond) // 請注意,這類似於 while 迴圈 bool cond = …; for (int i=0; cond; ++i) { cond = …; }

  • 輸入 (“”, 1) // 請注意,這類似於 do-while 迴圈 bool cond = true for (int i=0; cond; ++i) { cond = …; }

  • 輸入 (trip_count, “”) // 請注意,這類似於 for 迴圈 int trip_count = … for (int i=0; i < trip_count; ++i) { cond = …; // 已忽略 }

  • 輸入 (trip_count, cond) int trip_count = …; bool cond = …; for (int i=0; i < trip_count && cond; ++i) { cond = …; }

範例用法 - cond 以及行程計數

graph predict-net {
  %a = Constant[value = <Scalar Tensor [3]>]()
  %b = Constant[value = <Scalar Tensor [6]>]()
  %keepgoing = Constant[value = <Scalar Tensor [1]>]()
  %max_trip_count = Constant[value = <Scalar Tensor [10]>]()
  %keepgoing_out, %b_out, %user_defined_vals = Loop[body = <graph body-net>](%max_trip_count, %keepgoing, %b)
  return
}

graph body-net (
  %i[INT32, scalar]           // iteration number
  %keepgoing_in[BOOL, scalar] // incoming loop-termination-condition; not used
  %b_in[INT32, scalar]        // incoming value of loop-carried-dependency b
) {
  %my_local = Add(%a, %b_in)
  %b_out = Sub(%a, %b_in) // outgoing value of loop-carried-dependency b
  %keepgoing_out = Greater(%my_local, %b_out) // outgoing loop-termination-condition
  %user_defined_val = Add(%b_in, %b_in) // scan-output value to be accumulated
  return %keepgoing_out, %b_out, %user_defined_val
}

範例對等 C 程式碼

{
  /* User-defined code (enclosing scope) */
  int a = 3, b = 6;
  bool keepgoing = true; // Analogous to input cond
  /* End user-defined code */

  /* Implicitly-defined code */
  const int max_trip_count = 10; // Analogous to input M
  int user_defined_vals[]; // Imagine this is resizable
  /* End implicitly-defined code */
  /* initialize loop-carried variables and scan-output variables */
  bool keepgoing_out = keepgoing
  int b_out = b

  for (int i=0; i < max_trip_count && keepgoing_out; ++i) {
    /* Implicitly-defined code: bind actual parameter values
       to formal parameter variables of loop-body */
    bool keepgoing_in = keepgoing_out;
    bool b_in = b_out;

    /* User-defined code (loop body) */
    int my_local = a + b_in; // Reading value "a" from the enclosing scope is fine
    b_out = a - b_in;
    keepgoing_out = my_local > b_out;
    user_defined_val = b_in + b_in; // b_in and b_out are different variables
    /* End user-defined code */

    /* Implicitly defined-code */
    user_defined_vals[i] = user_defined_val // accumulate scan-output values
  }
  // int t = my_local; // Can't do this. my_local is not accessible here.

  // The values below are bound to the output variables of the loop and therefore accessible
  // b_out; user_defined_vals; keepgoing_out;
}

此程式碼片段中有幾點值得注意

  1. 來自封閉範圍 (亦即此處的變數「a」) 的值在範圍內,且可以在迴圈的輸入中參考。

  2. 迴圈主體中計算的任何需要在後續迭代中或在迴圈之後使用的值,都使用迴圈主體中的一對變數來建模,其中包含輸入變數 (例如 b_in) 和輸出變數 (例如 b_out)。這些稱為迴圈攜帶依賴項。迴圈運算節點會提供第一次迭代的輸入變數的輸入值,並傳回最終迭代產生的輸出變數的輸出值。

  3. 掃描輸出變數用於隱式串連所有迭代中計算的值。在上述範例中,所有迭代中計算的 user_defined_val 值會串連在一起,並在迴圈後傳回為 user_defined_vals 的值。

  4. 主體中建立的值無法在封閉範圍中存取,除非使用上述機制。

請注意,此運算子的語意支援「對角線」或「波前」執行。(請參閱此處的步驟 3 以取得範例:https://devblogs.nvidia.com/optimizing-recurrent-neural-networks-cudnn-5/)。前端應將多層 RNN 發射為一系列 While 運算子 (以時間作為內部迴圈維度),每個連續層會取用前一個層的 scan_outputs,並可能經過數個逐點運算子 (例如 dropout、殘差連線、線性層)。

子圖形的輸入/輸出 (由迴圈節點產生) 比對是根據順序而不是名稱。實作會根據此順序找出名稱。

屬性

  • body - GRAPH (必要)

    每次迭代執行的圖形。它有 2+N 個輸入:(iteration_num, condition, loop carried dependencies…)。它有 1+N+K 個輸出:(condition, loop carried dependencies…, scan_outputs…)。每個 scan_output 都是透過串連迴圈每次迭代結束時指定輸出值的值所建立。如果這些 scan_output 的維度或資料類型在迴圈迭代中變更,則會發生錯誤。

輸入

介於 2 到 2147483647 個輸入之間。

  • M (選用,異質) - I

    在執行階段指定的迴圈最大行程計數。選用。傳遞空字串則略過。

  • cond (選用,異質) - B

    布林終止條件。選用。傳遞空字串則略過。

  • v_initial (可變) - V

    任何迴圈攜帶依賴項的初始值 (在迴圈迭代中變更的值)

輸出

介於 1 到 2147483647 個輸出之間。

  • v_final_and_scan_outputs (可變) - V

    最後的 N 個迴圈攜帶依賴項值,然後是 K 個掃描輸出。掃描輸出必須是張量。

類型約束

  • V in ( optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(complex128))), optional(seq(tensor(complex64))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(complex128)), optional(tensor(complex64)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(float8e4m3fn)), optional(tensor(float8e4m3fnuz)), optional(tensor(float8e5m2)), optional(tensor(float8e5m2fnuz)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(complex128)), seq(tensor(complex64)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(complex128), tensor(complex64), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8) )

    所有 Tensor、Sequence(Tensor)、Optional(Tensor) 和 Optional(Sequence(Tensor)) 類型,最高支援至 IRv9。

  • I 的類型是 ( tensor(int64) )

    int64 類型的張量,應為純量。

  • B 的類型是 ( tensor(bool) )

    bool 類型的張量,應為純量。

迴圈 - 16

版本

  • 名稱迴圈 (GitHub)

  • 網域main

  • since_version: 16

  • 函式False

  • 支援等級SupportType.COMMON

  • 形狀推斷True

此運算子的版本自版本 16 起可用。

摘要

通用迴圈結構。此迴圈有多個終止條件

  1. 行程計數。在執行階段指定的迭代計數。透過指定輸入 M 來設定。選用。設定為空字串則省略。請注意,靜態行程計數 (在圖形建構時指定) 可以透過為輸入 M 傳入常數節點來指定。

  2. 迴圈終止條件。這是運算子的輸入,用於決定是否執行第一次迭代,也是主體圖形的迴圈攜帶依賴項。無論是否提供此輸入,主體圖形都必須為條件變數產生值。

此表格摘要說明此運算子的運作模式以及對等的 C 樣式程式碼

定義為 (max_trip_count, condition_var) 的運算子輸入。

  • 輸入 (“”, “”): for (int i=0; ; ++i) { cond = … // 請注意,會忽略此值,但主體中是必要值 }

  • 輸入 (“”, cond) // 請注意,這類似於 while 迴圈 bool cond = …; for (int i=0; cond; ++i) { cond = …; }

  • 輸入 (“”, 1) // 請注意,這類似於 do-while 迴圈 bool cond = true for (int i=0; cond; ++i) { cond = …; }

  • 輸入 (trip_count, “”) // 請注意,這類似於 for 迴圈 int trip_count = … for (int i=0; i < trip_count; ++i) { cond = …; // 已忽略 }

  • 輸入 (trip_count, cond) int trip_count = …; bool cond = …; for (int i=0; i < trip_count && cond; ++i) { cond = …; }

範例用法 - cond 以及行程計數

graph predict-net {
  %a = Constant[value = <Scalar Tensor [3]>]()
  %b = Constant[value = <Scalar Tensor [6]>]()
  %keepgoing = Constant[value = <Scalar Tensor [1]>]()
  %max_trip_count = Constant[value = <Scalar Tensor [10]>]()
  %keepgoing_out, %b_out, %user_defined_vals = Loop[body = <graph body-net>](%max_trip_count, %keepgoing, %b)
  return
}

graph body-net (
  %i[INT32, scalar]           // iteration number
  %keepgoing_in[BOOL, scalar] // incoming loop-termination-condition; not used
  %b_in[INT32, scalar]        // incoming value of loop-carried-dependency b
) {
  %my_local = Add(%a, %b_in)
  %b_out = Sub(%a, %b_in) // outgoing value of loop-carried-dependency b
  %keepgoing_out = Greater(%my_local, %b_out) // outgoing loop-termination-condition
  %user_defined_val = Add(%b_in, %b_in) // scan-output value to be accumulated
  return %keepgoing_out, %b_out, %user_defined_val
}

範例對等 C 程式碼

{
  /* User-defined code (enclosing scope) */
  int a = 3, b = 6;
  bool keepgoing = true; // Analogous to input cond
  /* End user-defined code */

  /* Implicitly-defined code */
  const int max_trip_count = 10; // Analogous to input M
  int user_defined_vals[]; // Imagine this is resizable
  /* End implicitly-defined code */
  /* initialize loop-carried variables and scan-output variables */
  bool keepgoing_out = keepgoing
  int b_out = b

  for (int i=0; i < max_trip_count && keepgoing_out; ++i) {
    /* Implicitly-defined code: bind actual parameter values
       to formal parameter variables of loop-body */
    bool keepgoing_in = keepgoing_out;
    bool b_in = b_out;

    /* User-defined code (loop body) */
    int my_local = a + b_in; // Reading value "a" from the enclosing scope is fine
    b_out = a - b_in;
    keepgoing_out = my_local > b_out;
    user_defined_val = b_in + b_in; // b_in and b_out are different variables
    /* End user-defined code */

    /* Implicitly defined-code */
    user_defined_vals[i] = user_defined_val // accumulate scan-output values
  }
  // int t = my_local; // Can't do this. my_local is not accessible here.

  // The values below are bound to the output variables of the loop and therefore accessible
  // b_out; user_defined_vals; keepgoing_out;
}

此程式碼片段中有幾點值得注意

  1. 來自封閉範圍 (亦即此處的變數「a」) 的值在範圍內,且可以在迴圈的輸入中參考。

  2. 迴圈主體中計算的任何需要在後續迭代中或在迴圈之後使用的值,都使用迴圈主體中的一對變數來建模,其中包含輸入變數 (例如 b_in) 和輸出變數 (例如 b_out)。這些稱為迴圈攜帶依賴項。迴圈運算節點會提供第一次迭代的輸入變數的輸入值,並傳回最終迭代產生的輸出變數的輸出值。

  3. 掃描輸出變數用於隱式串連所有迭代中計算的值。在上述範例中,所有迭代中計算的 user_defined_val 值會串連在一起,並在迴圈後傳回為 user_defined_vals 的值。

  4. 主體中建立的值無法在封閉範圍中存取,除非使用上述機制。

請注意,此運算子的語意支援「對角線」或「波前」執行。(請參閱此處的步驟 3 以取得範例:https://devblogs.nvidia.com/optimizing-recurrent-neural-networks-cudnn-5/)。前端應將多層 RNN 發射為一系列 While 運算子 (以時間作為內部迴圈維度),每個連續層會取用前一個層的 scan_outputs,並可能經過數個逐點運算子 (例如 dropout、殘差連線、線性層)。

子圖形的輸入/輸出 (由迴圈節點產生) 比對是根據順序而不是名稱。實作會根據此順序找出名稱。

屬性

  • body - GRAPH (必要)

    每次迭代執行的圖形。它有 2+N 個輸入:(iteration_num, condition, loop carried dependencies…)。它有 1+N+K 個輸出:(condition, loop carried dependencies…, scan_outputs…)。每個 scan_output 都是透過串連迴圈每次迭代結束時指定輸出值的值所建立。如果這些 scan_output 的維度或資料類型在迴圈迭代中變更,則會發生錯誤。

輸入

介於 2 到 2147483647 個輸入之間。

  • M (選用,異質) - I

    在執行階段指定的迴圈最大行程計數。選用。傳遞空字串則略過。

  • cond (選用,異質) - B

    布林終止條件。選用。傳遞空字串則略過。

  • v_initial (可變) - V

    任何迴圈攜帶依賴項的初始值 (在迴圈迭代中變更的值)

輸出

介於 1 到 2147483647 個輸出之間。

  • v_final_and_scan_outputs (可變) - V

    最後的 N 個迴圈攜帶依賴項值,然後是 K 個掃描輸出。掃描輸出必須是張量。

類型約束

  • V 的類型可以是 ( optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(complex128))), optional(seq(tensor(complex64))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(complex128)), optional(tensor(complex64)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(complex128)), seq(tensor(complex64)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(complex128), tensor(complex64), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8) )

    所有 Tensor、Sequence(Tensor)、Optional(Tensor) 和 Optional(Sequence(Tensor)) 類型,最高至 IRv4 版本。

  • I 的類型是 ( tensor(int64) )

    int64 類型的張量,應為純量。

  • B 的類型是 ( tensor(bool) )

    bool 類型的張量,應為純量。

迴圈 - 13

版本

  • 名稱迴圈 (GitHub)

  • 網域main

  • since_version: 13

  • 函式False

  • 支援等級SupportType.COMMON

  • 形狀推斷True

此版本的運算子從 13 版開始提供。

摘要

通用迴圈結構。此迴圈有多個終止條件

  1. 行程計數。在執行階段指定的迭代計數。透過指定輸入 M 來設定。選用。設定為空字串則省略。請注意,靜態行程計數 (在圖形建構時指定) 可以透過為輸入 M 傳入常數節點來指定。

  2. 迴圈終止條件。這是運算子的輸入,用於決定是否執行第一次迭代,也是主體圖形的迴圈攜帶依賴項。無論是否提供此輸入,主體圖形都必須為條件變數產生值。

此表格摘要說明此運算子的運作模式以及對等的 C 樣式程式碼

Operator inputs defined as (max_trip_count, condition_var).

input ("", ""):
    for (int i=0; ; ++i) {
      cond = ... // Note this value is ignored, but is required in the body
    }

input ("", cond) // Note this is analogous to a while loop
    bool cond = ...;
    for (int i=0; cond; ++i) {
      cond = ...;
    }

input ("", 1) // Note this is analogous to a do-while loop
    bool cond = true
    for (int i=0; cond; ++i) {
      cond = ...;
    }

input (trip_count, "") // Note this is analogous to a for loop
    int trip_count = ...
    for (int i=0; i < trip_count; ++i) {
      cond = ...; // ignored
    }

input (trip_count, cond)
    int trip_count = ...;
    bool cond = ...;
    for (int i=0; i < trip_count && cond; ++i) {
      cond = ...;
    }

範例用法 - cond 以及行程計數

graph predict-net {
  %a = Constant[value = <Scalar Tensor [3]>]()
  %b = Constant[value = <Scalar Tensor [6]>]()
  %keepgoing = Constant[value = <Scalar Tensor [1]>]()
  %max_trip_count = Constant[value = <Scalar Tensor [10]>]()
  %keepgoing_out, %b_out, %user_defined_vals = Loop[body = <graph body-net>](%max_trip_count, %keepgoing, %b)
  return
}

graph body-net (
  %i[INT32, scalar]           // iteration number
  %keepgoing_in[BOOL, scalar] // incoming loop-termination-condition; not used
  %b_in[INT32, scalar]        // incoming value of loop-carried-dependency b
) {
  %my_local = Add(%a, %b_in)
  %b_out = Sub(%a, %b_in) // outgoing value of loop-carried-dependency b
  %keepgoing_out = Greater(%my_local, %b_out) // outgoing loop-termination-condition
  %user_defined_val = Add(%b_in, %b_in) // scan-output value to be accumulated
  return %keepgoing_out, %b_out, %user_defined_val
}

範例對等 C 程式碼

{
  /* User-defined code (enclosing scope) */
  int a = 3, b = 6;
  bool keepgoing = true; // Analogous to input cond
  /* End user-defined code */

  /* Implicitly-defined code */
  const int max_trip_count = 10; // Analogous to input M
  int user_defined_vals[]; // Imagine this is resizable
  /* End implicitly-defined code */
  /* initialize loop-carried variables and scan-output variables */
  bool keepgoing_out = keepgoing
  int b_out = b

  for (int i=0; i < max_trip_count && keepgoing_out; ++i) {
    /* Implicitly-defined code: bind actual parameter values
       to formal parameter variables of loop-body */
    bool keepgoing_in = keepgoing_out;
    bool b_in = b_out;

    /* User-defined code (loop body) */
    int my_local = a + b_in; // Reading value "a" from the enclosing scope is fine
    b_out = a - b_in;
    keepgoing_out = my_local > b_out;
    user_defined_val = b_in + b_in; // b_in and b_out are different variables
    /* End user-defined code */

    /* Implicitly defined-code */
    user_defined_vals[i] = user_defined_val // accumulate scan-output values
  }
  // int t = my_local; // Can't do this. my_local is not accessible here.

  // The values below are bound to the output variables of the loop and therefore accessible
  // b_out; user_defined_vals; keepgoing_out;
}

此程式碼片段中有幾點值得注意

  1. 來自封閉範圍 (亦即此處的變數「a」) 的值在範圍內,且可以在迴圈的輸入中參考。

  2. 迴圈主體中計算的任何需要在後續迭代中或在迴圈之後使用的值,都使用迴圈主體中的一對變數來建模,其中包含輸入變數 (例如 b_in) 和輸出變數 (例如 b_out)。這些稱為迴圈攜帶依賴項。迴圈運算節點會提供第一次迭代的輸入變數的輸入值,並傳回最終迭代產生的輸出變數的輸出值。

  3. 掃描輸出變數用於隱式串連所有迭代中計算的值。在上述範例中,所有迭代中計算的 user_defined_val 值會串連在一起,並在迴圈後傳回為 user_defined_vals 的值。

  4. 主體中建立的值無法在封閉範圍中存取,除非使用上述機制。

請注意,此運算子的語意支援「對角線」或「波前」執行。(請參閱此處的步驟 3 以取得範例:https://devblogs.nvidia.com/optimizing-recurrent-neural-networks-cudnn-5/)。前端應將多層 RNN 發射為一系列 While 運算子 (以時間作為內部迴圈維度),每個連續層會取用前一個層的 scan_outputs,並可能經過數個逐點運算子 (例如 dropout、殘差連線、線性層)。

子圖形的輸入/輸出 (由迴圈節點產生) 比對是根據順序而不是名稱。實作會根據此順序找出名稱。

屬性

  • body - GRAPH (必要)

    每次迭代執行的圖形。它有 2+N 個輸入:(iteration_num, condition, loop carried dependencies…)。它有 1+N+K 個輸出:(condition, loop carried dependencies…, scan_outputs…)。每個 scan_output 都是透過串連迴圈每次迭代結束時指定輸出值的值所建立。如果這些 scan_output 的維度或資料類型在迴圈迭代中變更,則會發生錯誤。

輸入

介於 2 到 2147483647 個輸入之間。

  • M (選用,異質) - I

    在執行階段指定的迴圈最大行程計數。選用。傳遞空字串則略過。

  • cond (選用,異質) - B

    布林終止條件。選用。傳遞空字串則略過。

  • v_initial (可變) - V

    任何迴圈攜帶依賴項的初始值 (在迴圈迭代中變更的值)

輸出

介於 1 到 2147483647 個輸出之間。

  • v_final_and_scan_outputs (可變) - V

    最後的 N 個迴圈攜帶依賴項值,然後是 K 個掃描輸出。掃描輸出必須是張量。

類型約束

  • V 的類型可以是 ( seq(tensor(bool)), seq(tensor(complex128)), seq(tensor(complex64)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bool), tensor(complex128), tensor(complex64), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8) )

    所有 Tensor 和 Sequence 類型

  • I 的類型是 ( tensor(int64) )

    int64 類型的張量,應為純量。

  • B 的類型是 ( tensor(bool) )

    bool 類型的張量,應為純量。

迴圈 - 11

版本

  • 名稱迴圈 (GitHub)

  • 網域main

  • since_version: 11

  • 函式False

  • 支援等級SupportType.COMMON

  • 形狀推斷True

此版本的運算子從 11 版開始提供。

摘要

通用迴圈結構。此迴圈有多個終止條件

  1. 行程計數。在執行階段指定的迭代計數。透過指定輸入 M 來設定。選用。設定為空字串則省略。請注意,靜態行程計數 (在圖形建構時指定) 可以透過為輸入 M 傳入常數節點來指定。

  2. 迴圈終止條件。這是運算子的輸入,用於決定是否執行第一次迭代,也是主體圖形的迴圈攜帶依賴項。無論是否提供此輸入,主體圖形都必須為條件變數產生值。

此表格摘要說明此運算子的運作模式以及對等的 C 樣式程式碼

Operator inputs defined as (max_trip_count, condition_var).

input ("", ""):
    for (int i=0; ; ++i) {
      cond = ... // Note this value is ignored, but is required in the body
    }

input ("", cond) // Note this is analogous to a while loop
    bool cond = ...;
    for (int i=0; cond; ++i) {
      cond = ...;
    }

input ("", 1) // Note this is analogous to a do-while loop
    bool cond = true
    for (int i=0; cond; ++i) {
      cond = ...;
    }

input (trip_count, "") // Note this is analogous to a for loop
    int trip_count = ...
    for (int i=0; i < trip_count; ++i) {
      cond = ...; // ignored
    }

input (trip_count, cond)
    int trip_count = ...;
    bool cond = ...;
    for (int i=0; i < trip_count && cond; ++i) {
      cond = ...;
    }

範例用法 - cond 以及行程計數

graph predict-net {
  %a = Constant[value = <Scalar Tensor [3]>]()
  %b = Constant[value = <Scalar Tensor [6]>]()
  %keepgoing = Constant[value = <Scalar Tensor [1]>]()
  %max_trip_count = Constant[value = <Scalar Tensor [10]>]()
  %keepgoing_out, %b_out, %user_defined_vals = Loop[body = <graph body-net>](%max_trip_count, %keepgoing, %b)
  return
}

graph body-net (
  %i[INT32, scalar]           // iteration number
  %keepgoing_in[BOOL, scalar] // incoming loop-termination-condition; not used
  %b_in[INT32, scalar]        // incoming value of loop-carried-dependency b
) {
  %my_local = Add(%a, %b_in)
  %b_out = Sub(%a, %b_in) // outgoing value of loop-carried-dependency b
  %keepgoing_out = Greater(%my_local, %b_out) // outgoing loop-termination-condition
  %user_defined_val = Add(%b_in, %b_in) // scan-output value to be accumulated
  return %keepgoing_out, %b_out, %user_defined_val
}

範例對等 C 程式碼

{
  /* User-defined code (enclosing scope) */
  int a = 3, b = 6;
  bool keepgoing = true; // Analogous to input cond
  /* End user-defined code */

  /* Implicitly-defined code */
  const int max_trip_count = 10; // Analogous to input M
  int user_defined_vals[]; // Imagine this is resizable
  /* End implicitly-defined code */
  /* initialize loop-carried variables and scan-output variables */
  bool keepgoing_out = keepgoing
  int b_out = b

  for (int i=0; i < max_trip_count && keepgoing_out; ++i) {
    /* Implicitly-defined code: bind actual parameter values
       to formal parameter variables of loop-body */
    bool keepgoing_in = keepgoing_out;
    bool b_in = b_out;

    /* User-defined code (loop body) */
    int my_local = a + b_in; // Reading value "a" from the enclosing scope is fine
    b_out = a - b_in;
    keepgoing_out = my_local > b_out;
    user_defined_val = b_in + b_in; // b_in and b_out are different variables
    /* End user-defined code */

    /* Implicitly defined-code */
    user_defined_vals[i] = user_defined_val // accumulate scan-output values
  }
  // int t = my_local; // Can't do this. my_local is not accessible here.

  // The values below are bound to the output variables of the loop and therefore accessible
  // b_out; user_defined_vals; keepgoing_out;
}

此程式碼片段中有幾點值得注意

  1. 來自封閉範圍 (亦即此處的變數「a」) 的值在範圍內,且可以在迴圈的輸入中參考。

  2. 迴圈主體中計算的任何需要在後續迭代中或在迴圈之後使用的值,都使用迴圈主體中的一對變數來建模,其中包含輸入變數 (例如 b_in) 和輸出變數 (例如 b_out)。這些稱為迴圈攜帶依賴項。迴圈運算節點會提供第一次迭代的輸入變數的輸入值,並傳回最終迭代產生的輸出變數的輸出值。

  3. 掃描輸出變數用於隱式串連所有迭代中計算的值。在上述範例中,所有迭代中計算的 user_defined_val 值會串連在一起,並在迴圈後傳回為 user_defined_vals 的值。

  4. 主體中建立的值無法在封閉範圍中存取,除非使用上述機制。

請注意,此運算子的語意支援「對角線」或「波前」執行。(請參閱此處的步驟 3 以取得範例:https://devblogs.nvidia.com/optimizing-recurrent-neural-networks-cudnn-5/)。前端應將多層 RNN 發射為一系列 While 運算子 (以時間作為內部迴圈維度),每個連續層會取用前一個層的 scan_outputs,並可能經過數個逐點運算子 (例如 dropout、殘差連線、線性層)。

屬性

  • body - GRAPH (必要)

    每次迭代執行的圖形。它有 2+N 個輸入:(iteration_num, condition, loop carried dependencies…)。它有 1+N+K 個輸出:(condition, loop carried dependencies…, scan_outputs…)。每個 scan_output 都是透過串連迴圈每次迭代結束時指定輸出值的值所建立。如果這些 scan_output 的維度或資料類型在迴圈迭代中變更,則會發生錯誤。

輸入

介於 2 到 2147483647 個輸入之間。

  • M (選用,異質) - I

    在執行階段指定的迴圈最大行程計數。選用。傳遞空字串則略過。

  • cond (選用,異質) - B

    布林終止條件。選用。傳遞空字串則略過。

  • v_initial (可變) - V

    任何迴圈攜帶依賴項的初始值 (在迴圈迭代中變更的值)

輸出

介於 1 到 2147483647 個輸出之間。

  • v_final_and_scan_outputs (可變) - V

    最終的 N 個迴圈攜帶依賴值,然後是 K 個 scan_outputs

類型約束

  • V 的類型可以是 ( tensor(bool), tensor(complex128), tensor(complex64), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8) )

    所有 Tensor 類型

  • I 的類型是 ( tensor(int64) )

    int64 類型的張量,應為純量。

  • B 的類型是 ( tensor(bool) )

    bool 類型的張量,應為純量。

迴圈 - 1

版本

  • 名稱迴圈 (GitHub)

  • 網域main

  • since_version: 1

  • 函式False

  • 支援等級SupportType.COMMON

  • 形狀推斷True

此版本的運算子從 1 版開始提供。

摘要

通用迴圈結構。此迴圈有多個終止條件

  1. 行程計數。在執行階段指定的迭代計數。透過指定輸入 M 來設定。選用。設定為空字串則省略。請注意,靜態行程計數 (在圖形建構時指定) 可以透過為輸入 M 傳入常數節點來指定。

  2. 迴圈終止條件。這是運算子的輸入,用於決定是否執行第一次迭代,也是主體圖形的迴圈攜帶依賴項。無論是否提供此輸入,主體圖形都必須為條件變數產生值。

此表格摘要說明此運算子的運作模式以及對等的 C 樣式程式碼

Operator inputs defined as (max_trip_count, condition_var).

input ("", ""):
    for (int i=0; ; ++i) {
      cond = ... // Note this value is ignored, but is required in the body
    }

input ("", cond) // Note this is analogous to a while loop
    bool cond = ...;
    for (int i=0; cond; ++i) {
      cond = ...;
    }

input ("", 1) // Note this is analogous to a do-while loop
    bool cond = true
    for (int i=0; cond; ++i) {
      cond = ...;
    }

input (trip_count, "") // Note this is analogous to a for loop
    int trip_count = ...
    for (int i=0; i < trip_count; ++i) {
      cond = ...; // ignored
    }

input (trip_count, cond)
    int trip_count = ...;
    bool cond = ...;
    for (int i=0; i < trip_count && cond; ++i) {
      cond = ...;
    }

範例用法 - cond 以及行程計數

graph predict-net {
  %a = Constant[value = <Scalar Tensor [3]>]()
  %b = Constant[value = <Scalar Tensor [6]>]()
  %keepgoing = Constant[value = <Scalar Tensor [1]>]()
  %max_trip_count = Constant[value = <Scalar Tensor [10]>]()
  %keepgoing_out, %b_out, %user_defined_vals = Loop[body = <graph body-net>](%max_trip_count, %keepgoing, %b)
  return
}

graph body-net (
  %i[INT32, scalar]
  %keepgoing[BOOL, scalar]
  %b[INT32, scalar]
) {
  %my_local = Add(%a, %b)
  %b_out = Sub(%a, %b)
  %keepgoing_out = Greater(%my_local, %b_out)
  %user_defined_vals = Add(%b, %b)
  return %keepgoing_out, %b_out, %user_defined_vals
}

範例對等 C 程式碼

{
  /* User-defined code (enclosing scope) */
  int a = 3, b = 6;
  bool keepgoing = true; // Analogous to input cond
  /* End user-defined code */

  /* Implicitly-defined code */
  const int max_trip_count = 10; // Analogous to input M
  int user_defined_vals[]; // Imagine this is resizable
  /* End implicitly-defined code */
  for (int i=0; i < max_trip_count && keepgoing; ++i) {
    /* User-defined code (loop body) */
    int my_local = a + b; // Reading values in the enclosing scope is fine
    b = a - b; // writes fine if we specify b as a loop-carried dependency
    keepgoing = my_local > b; // keepgoing is a loop-carried dependency
    user_defined_vals[i] = b + b;
    /* End user-defined code */
  }
  // my_local = 123; // Can't do this. my_local was defined in the body

  // These below values are live-out from the loop and therefore accessible
  b_out; user_defined_vals; keepgoing_out;
}

此程式碼片段中有幾點值得注意

  1. 封閉範圍內的值(即此處的變數 a)在範圍內,並且可以在迴圈的輸入中被引用。

  2. 任何您希望在封閉範圍(即變數 b 和 keepgoing)中可用的變數,都必須聲明為迴圈攜帶的依賴項(在運算子輸入和輸出以及主體網路輸入和輸出中),或 scan_outputs。

  3. 在主體中建立的值無法在封閉範圍內存取。

請注意,此運算子的語意支援「對角線」或「波前」執行。(請參閱此處的步驟 3 以取得範例:https://devblogs.nvidia.com/optimizing-recurrent-neural-networks-cudnn-5/)。前端應將多層 RNN 發射為一系列 While 運算子 (以時間作為內部迴圈維度),每個連續層會取用前一個層的 scan_outputs,並可能經過數個逐點運算子 (例如 dropout、殘差連線、線性層)。

屬性

  • body - GRAPH (必要)

    每次迭代執行的圖形。它有 2+N 個輸入:(iteration_num, condition, loop carried dependencies…)。它有 1+N+K 個輸出:(condition, loop carried dependencies…, scan_outputs…)。每個 scan_output 都是透過串連迴圈每次迭代結束時指定輸出值的值所建立。如果這些 scan_output 的維度或資料類型在迴圈迭代中變更,則會發生錯誤。

輸入

介於 3 到 2147483647 個輸入之間。

  • M (選用,異質) - I

    在執行階段指定的迴圈最大行程計數。選用。傳遞空字串則略過。

  • cond (選用,異質) - B

    布林終止條件。選用。傳遞空字串則略過。

  • v_initial (可變) - V

    任何迴圈攜帶依賴項的初始值 (在迴圈迭代中變更的值)

輸出

介於 1 到 2147483647 個輸出之間。

  • v_final_and_scan_outputs (可變) - V

    最終的 N 個迴圈攜帶依賴值,然後是 K 個 scan_outputs

類型約束

  • V 的類型可以是 ( tensor(bool), tensor(complex128), tensor(complex64), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8) )

    所有 Tensor 類型

  • I 的類型是 ( tensor(int64) )

    int64 類型的張量,應為純量。

  • B 的類型是 ( tensor(bool) )

    bool 類型的張量,應為純量。