循环¶
循环 - 23¶
版本¶
名称: 循环 (GitHub)
域:
main
自版本:
23
函数:
False
支持级别:
SupportType.COMMON
形状推断:
True
此版本的运算符自版本 23起可用。
摘要¶
通用循环结构。此循环具有多个终止条件。
循环次数。在运行时指定的迭代次数。通过指定输入 M 来设置。可选。设置为空字符串以省略。请注意,可以通过为输入 M 传递一个常量节点来指定静态循环次数(在图构建时指定)。
循环终止条件。这是确定是否运行第一次迭代以及循环携带依赖项的运算符的输入。主体图必须为条件变量生成一个值,无论是否提供此输入。
此表总结了此运算符的操作模式以及等效的 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;
}
此代码片段中需要注意几点。
来自封闭作用域的值(例如,此处的变量“a”)在作用域内,可以在循环的输入中引用。
在循环主体中计算的任何需要在后续迭代或循环结束后使用,都使用循环主体中的一对变量建模,该对变量由输入变量(例如,b_in)和输出变量(例如,b_out)组成。这些称为循环携带依赖项。循环运算符节点为第一次迭代提供输入变量的输入值,并返回最后一次迭代产生的输出变量的输出值。
Scan_output 变量用于隐式连接跨所有迭代计算的值。在上面的示例中,在所有迭代中计算的 user_defined_val 的值被连接起来,并在循环结束后作为 user_defined_vals 的值返回。
在主体中创建的值无法在封闭作用域中访问,除非使用上面描述的机制。
请注意,此运算符的语义支持“对角线”或“波前”执行。(有关示例,请参阅此处的步骤 3:https://devblogs.nvidia.com/optimizing-recurrent-neural-networks-cudnn-5/)。前端应将多层 RNN 发射为一系列 While 运算符(其中时间是内部循环维度),其中每个后续层都使用前一层中的 scan_outputs,可能经过几个逐点运算符(例如,dropout、残差连接、线性层)。
子图(由循环节点生成)输入/输出匹配基于顺序而不是名称。实现将根据此顺序确定名称。
属性¶
body - 图(必需)
每次迭代运行的图。它有 2+N 个输入:(iteration_num,condition,loop carried dependencies…)。它有 1+N+K 个输出:(condition,loop carried dependencies…,scan_outputs…)。每个 scan_output 通过连接循环每次迭代结束时指定输出值的来创建。如果这些 scan_outputs 的维度或数据类型在循环迭代中发生变化,则会发生错误。
输入¶
2 到 2147483647 个输入。
M(可选,异构) - I
在运行时指定的循环的最大循环次数。可选。传递空字符串以跳过。
cond(可选,异构) - B
布尔终止条件。可选。传递空字符串以跳过。
v_initial(可变) - V
任何循环携带依赖项(跨循环迭代变化的值)的初始值。
输出¶
1 到 2147483647 个输出。
v_final_and_scan_outputs(可变) - V
最终 N 个循环携带依赖项值,然后是 K 个 scan_outputs。Scan 输出必须是张量。
类型约束¶
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** 起可用。
摘要¶
通用循环结构。此循环具有多个终止条件。
循环次数。在运行时指定的迭代次数。通过指定输入 M 来设置。可选。设置为空字符串以省略。请注意,可以通过为输入 M 传递一个常量节点来指定静态循环次数(在图构建时指定)。
循环终止条件。这是确定是否运行第一次迭代以及循环携带依赖项的运算符的输入。主体图必须为条件变量生成一个值,无论是否提供此输入。
此表总结了此运算符的操作模式以及等效的 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;
}
此代码片段中需要注意几点。
来自封闭作用域的值(例如,此处的变量“a”)在作用域内,可以在循环的输入中引用。
在循环主体中计算的任何需要在后续迭代或循环结束后使用,都使用循环主体中的一对变量建模,该对变量由输入变量(例如,b_in)和输出变量(例如,b_out)组成。这些称为循环携带依赖项。循环运算符节点为第一次迭代提供输入变量的输入值,并返回最后一次迭代产生的输出变量的输出值。
Scan_output 变量用于隐式连接跨所有迭代计算的值。在上面的示例中,在所有迭代中计算的 user_defined_val 的值被连接起来,并在循环结束后作为 user_defined_vals 的值返回。
在主体中创建的值无法在封闭作用域中访问,除非使用上面描述的机制。
请注意,此运算符的语义支持“对角线”或“波前”执行。(有关示例,请参阅此处的步骤 3:https://devblogs.nvidia.com/optimizing-recurrent-neural-networks-cudnn-5/)。前端应将多层 RNN 发射为一系列 While 运算符(其中时间是内部循环维度),其中每个后续层都使用前一层中的 scan_outputs,可能经过几个逐点运算符(例如,dropout、残差连接、线性层)。
子图(由循环节点生成)输入/输出匹配基于顺序而不是名称。实现将根据此顺序确定名称。
属性¶
body - 图(必需)
每次迭代运行的图。它有 2+N 个输入:(iteration_num,condition,loop carried dependencies…)。它有 1+N+K 个输出:(condition,loop carried dependencies…,scan_outputs…)。每个 scan_output 通过连接循环每次迭代结束时指定输出值的来创建。如果这些 scan_outputs 的维度或数据类型在循环迭代中发生变化,则会发生错误。
输入¶
2 到 2147483647 个输入。
M(可选,异构) - I
在运行时指定的循环的最大循环次数。可选。传递空字符串以跳过。
cond(可选,异构) - B
布尔终止条件。可选。传递空字符串以跳过。
v_initial(可变) - V
任何循环携带依赖项(跨循环迭代变化的值)的初始值。
输出¶
1 到 2147483647 个输出。
v_final_and_scan_outputs(可变) - V
最终 N 个循环携带依赖项值,然后是 K 个 scan_outputs。Scan 输出必须是张量。
类型约束¶
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(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)
)IRv10 版本之前的所有 Tensor、Sequence(Tensor)、Optional(Tensor) 和 Optional(Sequence(Tensor)) 类型。
I 的类型为 (
tensor(int64)
)int64 类型的张量,应为标量。
B 的类型为 (
tensor(bool)
)bool 类型的张量,应为标量。
循环 - 19¶
版本¶
名称: 循环 (GitHub)
域:
main
since_version:
19
函数:
False
支持级别:
SupportType.COMMON
形状推断:
True
此运算符版本自 **版本 19** 起可用。
摘要¶
通用循环结构。此循环具有多个终止条件。
循环次数。在运行时指定的迭代次数。通过指定输入 M 来设置。可选。设置为空字符串以省略。请注意,可以通过为输入 M 传递一个常量节点来指定静态循环次数(在图构建时指定)。
循环终止条件。这是确定是否运行第一次迭代以及循环携带依赖项的运算符的输入。主体图必须为条件变量生成一个值,无论是否提供此输入。
此表总结了此运算符的操作模式以及等效的 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;
}
此代码片段中需要注意几点。
来自封闭作用域的值(例如,此处的变量“a”)在作用域内,可以在循环的输入中引用。
在循环主体中计算的任何需要在后续迭代或循环结束后使用,都使用循环主体中的一对变量建模,该对变量由输入变量(例如,b_in)和输出变量(例如,b_out)组成。这些称为循环携带依赖项。循环运算符节点为第一次迭代提供输入变量的输入值,并返回最后一次迭代产生的输出变量的输出值。
Scan_output 变量用于隐式连接跨所有迭代计算的值。在上面的示例中,在所有迭代中计算的 user_defined_val 的值被连接起来,并在循环结束后作为 user_defined_vals 的值返回。
在主体中创建的值无法在封闭作用域中访问,除非使用上面描述的机制。
请注意,此运算符的语义支持“对角线”或“波前”执行。(有关示例,请参阅此处的步骤 3:https://devblogs.nvidia.com/optimizing-recurrent-neural-networks-cudnn-5/)。前端应将多层 RNN 发射为一系列 While 运算符(其中时间是内部循环维度),其中每个后续层都使用前一层中的 scan_outputs,可能经过几个逐点运算符(例如,dropout、残差连接、线性层)。
子图(由循环节点生成)输入/输出匹配基于顺序而不是名称。实现将根据此顺序确定名称。
属性¶
body - 图(必需)
每次迭代运行的图。它有 2+N 个输入:(iteration_num,condition,loop carried dependencies…)。它有 1+N+K 个输出:(condition,loop carried dependencies…,scan_outputs…)。每个 scan_output 通过连接循环每次迭代结束时指定输出值的来创建。如果这些 scan_outputs 的维度或数据类型在循环迭代中发生变化,则会发生错误。
输入¶
2 到 2147483647 个输入。
M(可选,异构) - I
在运行时指定的循环的最大循环次数。可选。传递空字符串以跳过。
cond(可选,异构) - B
布尔终止条件。可选。传递空字符串以跳过。
v_initial(可变) - V
任何循环携带依赖项(跨循环迭代变化的值)的初始值。
输出¶
1 到 2147483647 个输出。
v_final_and_scan_outputs(可变) - V
最终 N 个循环携带依赖项值,然后是 K 个 scan_outputs。Scan 输出必须是张量。
类型约束¶
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(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)
)IRv9 版本之前的所有 Tensor、Sequence(Tensor)、Optional(Tensor) 和 Optional(Sequence(Tensor)) 类型。
I 的类型为 (
tensor(int64)
)int64 类型的张量,应为标量。
B 的类型为 (
tensor(bool)
)bool 类型的张量,应为标量。
循环 - 16¶
版本¶
名称: 循环 (GitHub)
域:
main
since_version:
16
函数:
False
支持级别:
SupportType.COMMON
形状推断:
True
此运算符版本自 **版本 16** 起可用。
摘要¶
通用循环结构。此循环具有多个终止条件。
循环次数。在运行时指定的迭代次数。通过指定输入 M 来设置。可选。设置为空字符串以省略。请注意,可以通过为输入 M 传递一个常量节点来指定静态循环次数(在图构建时指定)。
循环终止条件。这是确定是否运行第一次迭代以及循环携带依赖项的运算符的输入。主体图必须为条件变量生成一个值,无论是否提供此输入。
此表总结了此运算符的操作模式以及等效的 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;
}
此代码片段中需要注意几点。
来自封闭作用域的值(例如,此处的变量“a”)在作用域内,可以在循环的输入中引用。
在循环主体中计算的任何需要在后续迭代或循环结束后使用,都使用循环主体中的一对变量建模,该对变量由输入变量(例如,b_in)和输出变量(例如,b_out)组成。这些称为循环携带依赖项。循环运算符节点为第一次迭代提供输入变量的输入值,并返回最后一次迭代产生的输出变量的输出值。
Scan_output 变量用于隐式连接跨所有迭代计算的值。在上面的示例中,在所有迭代中计算的 user_defined_val 的值被连接起来,并在循环结束后作为 user_defined_vals 的值返回。
在主体中创建的值无法在封闭作用域中访问,除非使用上面描述的机制。
请注意,此运算符的语义支持“对角线”或“波前”执行。(有关示例,请参阅此处的步骤 3:https://devblogs.nvidia.com/optimizing-recurrent-neural-networks-cudnn-5/)。前端应将多层 RNN 发射为一系列 While 运算符(其中时间是内部循环维度),其中每个后续层都使用前一层中的 scan_outputs,可能经过几个逐点运算符(例如,dropout、残差连接、线性层)。
子图(由循环节点生成)输入/输出匹配基于顺序而不是名称。实现将根据此顺序确定名称。
属性¶
body - 图(必需)
每次迭代运行的图。它有 2+N 个输入:(iteration_num,condition,loop carried dependencies…)。它有 1+N+K 个输出:(condition,loop carried dependencies…,scan_outputs…)。每个 scan_output 通过连接循环每次迭代结束时指定输出值的来创建。如果这些 scan_outputs 的维度或数据类型在循环迭代中发生变化,则会发生错误。
输入¶
2 到 2147483647 个输入。
M(可选,异构) - I
在运行时指定的循环的最大循环次数。可选。传递空字符串以跳过。
cond(可选,异构) - B
布尔终止条件。可选。传递空字符串以跳过。
v_initial(可变) - V
任何循环携带依赖项(跨循环迭代变化的值)的初始值。
输出¶
1 到 2147483647 个输出。
v_final_and_scan_outputs(可变) - V
最终 N 个循环携带依赖项值,然后是 K 个 scan_outputs。Scan 输出必须是张量。
类型约束¶
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)
)在 IRv4 之前,所有 Tensor、Sequence(Tensor)、Optional(Tensor) 和 Optional(Sequence(Tensor)) 类型。
I 的类型为 (
tensor(int64)
)int64 类型的张量,应为标量。
B 的类型为 (
tensor(bool)
)bool 类型的张量,应为标量。
循环 - 13¶
版本¶
名称: 循环 (GitHub)
域:
main
since_version:
13
函数:
False
支持级别:
SupportType.COMMON
形状推断:
True
此运算符版本自版本 13起可用。
摘要¶
通用循环结构。此循环具有多个终止条件。
循环次数。在运行时指定的迭代次数。通过指定输入 M 来设置。可选。设置为空字符串以省略。请注意,可以通过为输入 M 传递一个常量节点来指定静态循环次数(在图构建时指定)。
循环终止条件。这是确定是否运行第一次迭代以及循环携带依赖项的运算符的输入。主体图必须为条件变量生成一个值,无论是否提供此输入。
此表总结了此运算符的操作模式以及等效的 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;
}
此代码片段中需要注意几点。
来自封闭作用域的值(例如,此处的变量“a”)在作用域内,可以在循环的输入中引用。
在循环主体中计算的任何需要在后续迭代或循环结束后使用,都使用循环主体中的一对变量建模,该对变量由输入变量(例如,b_in)和输出变量(例如,b_out)组成。这些称为循环携带依赖项。循环运算符节点为第一次迭代提供输入变量的输入值,并返回最后一次迭代产生的输出变量的输出值。
Scan_output 变量用于隐式连接跨所有迭代计算的值。在上面的示例中,在所有迭代中计算的 user_defined_val 的值被连接起来,并在循环结束后作为 user_defined_vals 的值返回。
在主体中创建的值无法在封闭作用域中访问,除非使用上面描述的机制。
请注意,此运算符的语义支持“对角线”或“波前”执行。(有关示例,请参阅此处的步骤 3:https://devblogs.nvidia.com/optimizing-recurrent-neural-networks-cudnn-5/)。前端应将多层 RNN 发射为一系列 While 运算符(其中时间是内部循环维度),其中每个后续层都使用前一层中的 scan_outputs,可能经过几个逐点运算符(例如,dropout、残差连接、线性层)。
子图(由循环节点生成)输入/输出匹配基于顺序而不是名称。实现将根据此顺序确定名称。
属性¶
body - 图(必需)
每次迭代运行的图。它有 2+N 个输入:(iteration_num,condition,loop carried dependencies…)。它有 1+N+K 个输出:(condition,loop carried dependencies…,scan_outputs…)。每个 scan_output 通过连接循环每次迭代结束时指定输出值的来创建。如果这些 scan_outputs 的维度或数据类型在循环迭代中发生变化,则会发生错误。
输入¶
2 到 2147483647 个输入。
M(可选,异构) - I
在运行时指定的循环的最大循环次数。可选。传递空字符串以跳过。
cond(可选,异构) - B
布尔终止条件。可选。传递空字符串以跳过。
v_initial(可变) - V
任何循环携带依赖项(跨循环迭代变化的值)的初始值。
输出¶
1 到 2147483647 个输出。
v_final_and_scan_outputs(可变) - V
最终 N 个循环携带依赖项值,然后是 K 个 scan_outputs。Scan 输出必须是张量。
类型约束¶
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起可用。
摘要¶
通用循环结构。此循环具有多个终止条件。
循环次数。在运行时指定的迭代次数。通过指定输入 M 来设置。可选。设置为空字符串以省略。请注意,可以通过为输入 M 传递一个常量节点来指定静态循环次数(在图构建时指定)。
循环终止条件。这是确定是否运行第一次迭代以及循环携带依赖项的运算符的输入。主体图必须为条件变量生成一个值,无论是否提供此输入。
此表总结了此运算符的操作模式以及等效的 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;
}
此代码片段中需要注意几点。
来自封闭作用域的值(例如,此处的变量“a”)在作用域内,可以在循环的输入中引用。
在循环主体中计算的任何需要在后续迭代或循环结束后使用,都使用循环主体中的一对变量建模,该对变量由输入变量(例如,b_in)和输出变量(例如,b_out)组成。这些称为循环携带依赖项。循环运算符节点为第一次迭代提供输入变量的输入值,并返回最后一次迭代产生的输出变量的输出值。
Scan_output 变量用于隐式连接跨所有迭代计算的值。在上面的示例中,在所有迭代中计算的 user_defined_val 的值被连接起来,并在循环结束后作为 user_defined_vals 的值返回。
在主体中创建的值无法在封闭作用域中访问,除非使用上面描述的机制。
请注意,此运算符的语义支持“对角线”或“波前”执行。(有关示例,请参阅此处的步骤 3:https://devblogs.nvidia.com/optimizing-recurrent-neural-networks-cudnn-5/)。前端应将多层 RNN 发射为一系列 While 运算符(其中时间是内部循环维度),其中每个后续层都使用前一层中的 scan_outputs,可能经过几个逐点运算符(例如,dropout、残差连接、线性层)。
属性¶
body - 图(必需)
每次迭代运行的图。它有 2+N 个输入:(iteration_num,condition,loop carried dependencies…)。它有 1+N+K 个输出:(condition,loop carried dependencies…,scan_outputs…)。每个 scan_output 通过连接循环每次迭代结束时指定输出值的来创建。如果这些 scan_outputs 的维度或数据类型在循环迭代中发生变化,则会发生错误。
输入¶
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起可用。
摘要¶
通用循环结构。此循环具有多个终止条件。
循环次数。在运行时指定的迭代次数。通过指定输入 M 来设置。可选。设置为空字符串以省略。请注意,可以通过为输入 M 传递一个常量节点来指定静态循环次数(在图构建时指定)。
循环终止条件。这是确定是否运行第一次迭代以及循环携带依赖项的运算符的输入。主体图必须为条件变量生成一个值,无论是否提供此输入。
此表总结了此运算符的操作模式以及等效的 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;
}
此代码片段中需要注意几点。
来自封闭作用域的值(例如,此处的变量 a)在作用域内,可以在循环的输入中引用。
您希望在封闭作用域中可用的任何变量(例如,变量 b 和 keepgoing)必须声明为循环携带的依赖项(在运算符输入和输出以及主体网络输入和输出处)或 scan_outputs。
主体中创建的值无法在封闭作用域中访问。
请注意,此运算符的语义支持“对角线”或“波前”执行。(有关示例,请参阅此处的步骤 3:https://devblogs.nvidia.com/optimizing-recurrent-neural-networks-cudnn-5/)。前端应将多层 RNN 发射为一系列 While 运算符(其中时间是内部循环维度),其中每个后续层都使用前一层中的 scan_outputs,可能经过几个逐点运算符(例如,dropout、残差连接、线性层)。
属性¶
body - 图(必需)
每次迭代运行的图。它有 2+N 个输入:(iteration_num,condition,loop carried dependencies…)。它有 1+N+K 个输出:(condition,loop carried dependencies…,scan_outputs…)。每个 scan_output 通过连接循环每次迭代结束时指定输出值的来创建。如果这些 scan_outputs 的维度或数据类型在循环迭代中发生变化,则会发生错误。
输入¶
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 类型的张量,应为标量。