主要内容

的变量分类parfor循环

概述

MATLAB®编码器™对象中的变量进行分类parfor-循环到下表中的一个类别。它不支持无法分类的变量。万博1manbetx如果一个parfor-loop包含不能唯一分类的变量,或者如果一个变量违反了它的分类限制,则parfor-loop产生错误。

分类 描述
循环 用作数组的循环索引
切片 一种数组,其分段由循环的不同迭代操作
广播 在循环之前定义的变量,其值在循环内部使用,但不在循环内部赋值
减少 在循环的多个迭代中累积值,而不考虑迭代顺序
临时 在循环内部创建的变量,但与切片或还原变量不同,在循环外部不可用

这些变量分类都出现在以下代码片段中:

= 0;c =π;z = 0;r =兰德(10);Parfor i=1:10 a=i;% 'a'是一个临时变量z=z+i;% 'z'是一个约简变量b(i)=r(i);% 'b'是一个切片输出变量;% 'r'是切片输入变量,如果i<=c % 'c'是广播变量d=2*a;% 'd'是临时变量end end

切变量

一个切变量它的值可以被分割成多个部分,或者,然后由不同的线程分别操作。循环的每次迭代都作用于数组的不同部分。

在下一个例子中,一片一个由该数组的单个元素组成:

parfor i = 1:长度(A) B(i) = f(A(i));结束

切片变量的特征

的变量parfor-loop如果具有以下特征则被切片:

  • 第一级索引的类型——第一级索引是圆括号,()

  • 固定索引列表——在第一级括号中,对于给定变量的所有出现,索引列表都是相同的。

  • 索引的形式——在变量的索引列表中,只有一个索引涉及循环变量。

  • 数组的形状——在给切片变量赋值时,赋值的右边不是[](这些操作符表示删除元素)。

一级索引的类型.对于切片变量,第一级索引被括在括号中,().例如,(…).如果使用点表示法引用变量,A.x,该变量没有切片。

变量一个左边是没有切片的;变量一个右边是切片图:

A.q(我12)(我12)。q

固定索引清单.在切片变量索引的第一级括号内,对于给定变量的所有出现,索引列表都是相同的。

变量B左边没有切片,因为B而且我+ 1在不同的地方。变量B右边是切片。

B(i) = B(i+1) +1;结束
B(i+1) = B(i+1) +1;结束

索引表格.在切片变量的索引列表中,有一个索引的形式为我+ ki (kk +我,或k-i

  • 是循环变量。

  • k是常量或简单(非索引)变量。

  • 其他索引都是常量、简单变量、冒号或结束

当使用其他变量和循环变量一起索引数组时,不能在循环内部设置这些变量。这些变量在整个执行过程中是恒定的parfor声明。不能将循环变量与其自身组合以形成索引表达式。

在下面的例子中,是循环变量,j而且k是非索引变量。

变量A没有切片 变量A被切片
A(i+f(k),j,:,3) A(i,20:30,end)
A(i+k,j,:,3) A(i,:,end) A(i,:,k)

阵列形状.切片变量必须保持恒定的形状。在以下示例中,变量一个未切片:

A(i,:) = [];A(end + 1) = i;

广播变量

一个广播变量是循环变量以外的变量或在循环内部未修改的切片变量。

减少变量

一个减少变量累积一个值,该值依赖于所有的迭代,但与迭代顺序无关。

此示例显示了parfor-循环,使用标量约简赋值。它使用约简变量x积累:在…上积累一笔钱10循环的迭代。线程上迭代的执行顺序并不重要。

X = 0;Parfor I = 1:10 x = x + I;结束x

在哪里expr是一个MATLAB表达式,约简变量出现在赋值语句的两侧。

X = X + expr X = expr + X
X = X - expr 看到约简函数的约简赋值、结合性和交换性
X = X .* expr X = expr .* X
X = X * expr X = expr * X
X = X & expr X = expr & X
X = X | expr X = expr | X
X = min(X, expr) X = min(expr, X)
X = max(X, expr) X = max(expr, X)
X = f (X, expr)
函数f必须是用户定义的函数。
X = f(expr, X)
看到约简函数的约简赋值、结合性和交换性

每个被允许的语句都被称为a减少作业.约简变量只能出现在这种类型的赋值中。

下面的示例展示了简化变量的典型用法X

X =…;做一些初始化X parfor i = 1:n X = X + d(i);结束

这个循环等价于下面,其中每个d(我)由不同的迭代计算:

X = X + d(1) +…+ d (n)

如果这个循环是正则的-loop,变量X在每次迭代中,要么在进入循环之前获得它的值,要么从循环的前一次迭代中获得它的值。然而,这一概念并不适用于parfor循环。

在一个parfor-loop,的值X不直接在每个线程内部更新。而是增加d(我)都在每个线程中完成,用的子集1: n在该线程上执行。然后软件将结果累积成X

类似地,缩略语:

r = r < op > x(我)
相当于:
r = r < op > x (1)] < op >(2)…< op > x (n)
操作< op >首先应用于x(1)……(n),则将部分结果应用于r

如果操作< op >接受两个输入,它应该满足以下条件之一:

  • 取两个论点typeof (x (i))并返回typeof (x (i))

  • 取一个论证typeof(右)其中一个typeof (x (i))并返回typeof(右)

约简变量规则

在所有约简赋值中使用相同的约简函数或运算。对于一个约简变量,必须在该变量的所有约简赋值中使用相同的约简函数或操作。在下面的例子中,parfor-loop是无效的,因为约简赋值使用+在一个例子中,和在另一个。

无效使用约简变量 有效使用约简变量
if A > 5*k A = A + 1;否则A = A * 2;结束
parfor i = 1: if A > 5*k A = A * 3;否则A = A * 2;结束

约简函数参数和返回类型的限制。减少r = r < op > x(我),应采取的论据typeof (x (i))并返回typeof (x (i))或者取typeof(右)而且typeof (x (i))并返回typeof(右)

在下面的例子中,在无效循环中,r是定点类型和2不是。要解决此问题,请cast2与…属于同一类型r

无效使用约简变量 有效使用约简变量
function r= fiops(in) r=fi(in,'WordLength',20,…“FractionLength”,14日……“SumMode”、“SpecifyPrecision’,……“SumWordLength”,20日……“SumFractionLength”,14日……“ProductMode”、“SpecifyPrecision’,……“ProductWordLength”,20日……“ProductFractionLength”,14);Parfor I = 1:10 r = r*2;结束
r = fi(“字”,20日…“FractionLength”,14日……“SumMode”、“SpecifyPrecision’,……“SumWordLength”,20日……“SumFractionLength”,14日……“ProductMode”、“SpecifyPrecision’,……“ProductWordLength”,20日……“ProductFractionLength”,14);T = r.numerictype;F = r.fimath; parfor i = 1:10 r = r*fi(2,T,F); end

在下面的例子中,约简函数fcn无效,因为它不处理输入时的情况u是定点。(+而且操作是自动多态的。)的多态版本fcn来处理预期的输入类型。

无效使用约简变量 有效使用约简变量
函数[y0, y1, y2] = pfuserfcn(u) y0 = 0;y = 1;[F, N] = fiprops();y2 = fi(1,N,F);Parfor (i=1:numel(u),12) y0 = y0 + u(i);y = y * u(i);Y2 = fcn(Y2, u(i));结束结束函数y = fcn(u, v) y = u * v;结束
函数[y0, y1, y2] = pfuserfcn(u) y0 = 0;y = 1;[F, N] = fiprops();y2 = fi(1,N,F);Parfor (i=1:numel(u),12) y0 = y0 + u(i);y = y * u(i);Y2 = fcn(Y2, u(i));如果isa(u,'double') y = u * v,则处理类型double %和fi函数y = FCN (u, v);else [F, N] = fiprops();y = u * fi(v,N,F); end end function [F, N] = fiprops() N = numerictype(1,96,30); F = fimath('ProductMode',... 'SpecifyPrecision',... 'ProductWordLength',96); end

约简函数的约简赋值、结合性和交换性

减少作业MATLAB编码器的任何地方都不允许读约简变量parfor-循环除约简语句。在下面的示例中,调用foo(右)在缩减报表之后r = r +我导致循环无效。

函数r = temp %#codegen r = 0;r = r + i;foo (r);结束结束

约简作业中的结合性。如果使用用户定义的函数f在约简变量的定义中,得到的确定性行为parfor-loops,约简函数f必须是结合律。

请注意

如果f没有联想性,MATLAB编码器不会产生错误。您必须编写符合这个建议的代码。

要结合律,函数f必须满足以下所有条件吗一个b,c

F (a, F (b,c)) = F (F (a,b),c)

约简分配中的交换性。一些结合律函数,包括+最小值,马克斯,也是交换律。也就是说,它们满足以下所有条件一个而且b

F (a,b) = F (b,a)

这个函数f约简分配必须是可交换的。如果f不是交换的,不同的循环执行可能导致不同的答案。

除非f是已知的非交换内置,软件假定它是交换的。

临时变量

一个临时变量是直接非索引赋值的目标变量,但不是约简变量。在下面parfor循环,一个而且d是临时变量:

A = 0;Z = 0;R = rand(1,10);Parfor I = 1:10 a = I;%变量a是临时z = z + i;如果I <= 5 d = 2*a;变量d是临时结束

与之相反的是的每次迭代之前parfor循环,MATLAB编码器有效清除临时变量。因为迭代必须是独立的,所以临时变量的值不能从循环的一个迭代传递到另一个迭代。因此,必须在类的对象内部设置临时变量parfor-loop,以便为每次迭代分别定义它们的值。

的上下文中的临时变量parfor语句与存在于循环外部的具有相同名称的变量不同。

未初始化的临时变量

因为临时变量在每次迭代开始时都被清除,MATLAB编码器可以检测通过循环的迭代在该迭代中设置临时变量之前使用该临时变量的某些情况。在这种情况下,MATLAB编码器发出静态错误而不是运行时错误,因为如果将发生运行时错误,那么允许继续执行几乎没有意义。例如,假设你这样写:

B = true;I = 1:n if b && some_condition(I) do_something(I);B =假;结束……结束

这个循环作为普通循环是可以接受的-loop,但作为parfor循环,b是一个临时变量,因为它直接作为循环内赋值的目标出现。因此,它在每次迭代开始时被清除,因此它在的条件下使用如果是未初始化的。(如果你改变parfor的价值。b假设循环顺序执行,因此do_something(我)仅对的较低值执行直到b设置.)