主要内容

自定义训练循环的深度学习函数加速

当使用dlfeval函数在自定义训练循环,软件跟踪每个输入dlarray对象的模型损失函数的确定计算用于图的自动判别。此跟踪过程可能会花费一些时间,并且可能会花费时间重新计算相同的跟踪。通过优化、缓存和重用跟踪,可以加速深度学习函数中的梯度计算。您还可以优化、缓存和重用跟踪来加速其他不需要自动区分的深度学习函数,例如,您还可以加速用于预测的模型函数和函数。

要加快对深度学习函数的调用,可以使用dlaccelerate函数创建AcceleratedFunction对象,该对象自动优化、缓存和重用跟踪。您可以使用dlaccelerate函数直接加速模型函数和模型损失函数。

返回的AcceleratedFunction对象缓存对底层函数的调用跟踪,并在再次出现相同的输入模式时重用缓存的结果。

试着用dlaccelerate对于函数调用:

  • 是长时间运行的

  • dlarray对象、结构dlarray对象,或dlnetwork对象作为输入

  • 没有副作用,如写入文件或显示输出

像调用底层函数一样调用加速函数。注意,加速函数不是一个函数句柄。

请注意

当使用dlfeval功能,软件自动加速向前而且预测功能dlnetwork输入。如果你加速一个深度学习函数,其中大部分计算发生在调用向前预测功能dlnetwork输入,那么你可能看不到训练时间的改善。

由于缓存跟踪的性质,并非所有函数都支持加速。金宝app

缓存过程可以缓存您可能希望更改的值或依赖于外部因素的值。当加速函数时,你必须小心:

  • 是否有随机或频繁变化的值的输入

  • 输出值经常变化

  • 生成随机数

  • 使用如果语句和的值作为条件的循环dlarray对象

  • 输入是句柄还是依赖句柄

  • 从外部源读取数据(例如,通过使用数据存储或minibatchqueue对象)

由于缓存过程需要额外的计算,在某些情况下,加速会导致代码运行时间更长。当软件花费时间创建不经常重用的新缓存时,就会发生这种情况。例如,当您将多个不同序列长度的小批量传递给该函数时,软件将为每个独特的序列长度触发一个新的跟踪。

加速函数只能在计算新轨迹时执行以下操作。

  • 修改全局状态,如随机数流或全局变量

  • 使用文件输入或输出

  • 使用图形或命令行显示显示数据

当并行使用加速函数时,例如当使用parfor循环,然后每个worker维护自己的缓存。缓存没有传输给主机。

加速函数中使用的函数和自定义层也必须支持加速。金宝app

可以嵌套和递归调用加速函数。然而,使用单个加速函数通常效率更高。

直接加速深度学习功能

在大多数情况下,您可以直接加速深度学习函数。例如,你可以直接加速模型损失函数,方法是用对相应加速函数的调用替换对模型损失函数的调用:

的下面的用法dlfeval在自定义训练循环中函数。

[loss,gradients,state] = dlfeval(@modelLoss,parameters,X,T,state)
要加速模型损失函数并计算加速函数,请使用dlaccelerate函数并计算返回的值AcceleratedFunction对象:
accfun = dlaccelerate(@modelLoss);[loss,gradients,state] = dlfeval(accfun,parameters,X,T,state)

对象的缓存跟踪没有直接附加到AcceleratedFunction对象及其共享对象AcceleratedFunction对象使用相同的底层函数时,可以创建AcceleratedFunction在自定义训练循环体中或之前。

加速部分深度学习功能

如果深度学习函数不完全支持加速,例如,需要加速的函数金宝app如果语句,其条件取决于a的值dlarray对象,然后您可以通过创建包含您希望加速的任何受支持函数调用的单独函数来加速深度学习函数的部分。金宝app

的和是否调用不同的函数,考虑下面的代码段dlarray对象X是负的还是非负的。

如果总和(X,“所有”< 0 Y = negFun1(参数,X);Y = negFun2(参数,Y);其他的Y = posFun1(参数,X);Y = posFun2(参数,Y);结束

因为如果语句依赖于a的值dlarray对象时,包含此代码段的函数不支持加速。金宝app但是,如果代码块使用在体的内部如果语句支持加速,那么您金宝app可以通过创建一个包含这些块的新函数来分别加速这些部分,而不是加速新函数。

例如,创建函数negFunAll而且posFunAll类体中使用的代码块如果声明。

函数Y = negFun1(参数,X);Y = negFun2(参数,Y);结束函数Y = posFun1(参数,X);Y = posFun2(参数,Y);结束
然后,加速这些函数并在体中使用它们如果语句代替。
accfunNeg = dlaccelerate(@negFunAll) accfunPos = dlaccelerate(@posFunAll)如果总和(X,“所有”Y = accfunNeg(参数,X);其他的Y = accfunPos(参数,X);结束

重用缓存

重用缓存的跟踪依赖于函数的输入和输出:

  • 对于任何dlarray物体或结构dlarray对象输入时,跟踪取决于对象的大小、格式和底层数据类型dlarray.也就是说,加速函数触发一个新的跟踪dlarray缓存中不包含大小、格式或底层数据类型的输入。任何dlarray仅与先前缓存的跟踪值不同的输入不会触发新的跟踪。

  • 对于任何dlnetwork类的大小、格式和底层数据类型dlnetwork状态和可学习参数。也就是说,加速函数触发一个新的跟踪dlnetwork缓存中不包含具有大小、格式和底层数据类型的可学习参数或状态的输入。任何dlnetwork仅在先前缓存的跟踪的状态值和可学习参数值之间存在差异的输入不会触发新的跟踪。

  • 对于其他类型的输入,跟踪依赖于输入的值。也就是说,加速函数为缓存中不包含值的其他类型的输入触发新的跟踪。与先前缓存的跟踪具有相同值的任何其他输入都不会触发新的跟踪。

  • 跟踪依赖于函数输出的数量。也就是说,加速函数触发一个新的跟踪函数调用,其中包含以前未见过的输出参数数量。与先前缓存的跟踪具有相同数量输出参数的任何函数调用都不会触发新的跟踪。

必要时,软件通过计算底层函数并将结果跟踪缓存到AcceleratedFunction对象。

谨慎

一个AcceleratedFunction对象不知道底层函数的更新。方法修改与加速函数关联的函数,则使用clearCache对象函数,或者使用该命令明确的功能

存储和清除缓存

AcceleratedFunction对象将缓存存储在队列中:

  • 软件将新的跟踪添加到队列的后面。

  • 当缓存已满时,软件将丢弃位于队列头部的缓存项。

  • 当缓存被重用时,软件将缓存项移到队列的后面。这有助于防止软件丢弃通常重用的缓存项。

AcceleratedFunction对象不直接保存缓存。这意味着:

  • 多个AcceleratedFunction具有相同底层函数的对象共享相同的缓存。

  • 对象的变量清除或覆盖AcceleratedFunction对象不能清除缓存。

  • 对象的变量重写AcceleratedFunction与另一个AcceleratedFunction与底层相同的函数不清除缓存。

具有相同底层函数的加速函数共享相同的缓存。

要清除加速函数的缓存,请使用clearCache对象的功能。或者,您可以清除当前MATLAB中的所有函数®会话使用命令明确的功能清除所有

请注意

清理AcceleratedFunction变量不清除与输入函数关联的缓存。对象的缓存清除AcceleratedFunction对象中不再存在的对象,创建一个新的AcceleratedFunction对象设置为相同的函数,并使用clearCache函数在新对象上。或者,您可以使用命令清除当前MATLAB会话中的所有函数明确的功能清除所有

加速度的考虑

由于缓存跟踪的性质,并非所有函数都支持加速。金宝app

缓存过程可以缓存您可能希望更改的值或依赖于外部因素的值。当加速函数时,你必须小心:

  • 是否有随机或频繁变化的值的输入

  • 输出值经常变化

  • 生成随机数

  • 使用如果语句和的值作为条件的循环dlarray对象

  • 输入是句柄还是依赖句柄

  • 从外部源读取数据(例如,通过使用数据存储或minibatchqueue对象)

由于缓存过程需要额外的计算,在某些情况下,加速会导致代码运行时间更长。当软件花费时间创建不经常重用的新缓存时,就会发生这种情况。例如,当您将多个不同序列长度的小批量传递给该函数时,软件将为每个独特的序列长度触发一个新的跟踪。

加速函数只能在计算新轨迹时执行以下操作。

  • 修改全局状态,如随机数流或全局变量

  • 使用文件输入或输出

  • 使用图形或命令行显示显示数据

当并行使用加速函数时,例如当使用parfor循环,然后每个worker维护自己的缓存。缓存没有传输给主机。

加速函数中使用的函数和自定义层也必须支持加速。金宝app

具有随机或频繁变化值的函数输入

当加速以随机或频繁变化的值作为输入的函数时,您必须小心,例如将随机噪声作为输入并将其添加到输入数据的模型损失函数。如果对加速函数的任意随机或频繁变化的输入不是dlarray对象,然后函数为每个以前未看到的值触发一个新的跟踪。

方法来检查类似的场景入住率而且HitRate的属性AcceleratedFunction对象。如果入住率房产价格高HitRate是低的,那么这可以说明AcceleratedFunction对象创建了许多未重用的新跟踪。

dlarray对象输入时,值的更改不会触发新的跟踪。为了防止频繁更改输入触发对每个计算的新跟踪,重构代码,使随机输入为dlarray输入。

例如,考虑接受随机噪声值数组的模型损失函数:

函数[loss,gradients,state] = modelLoss(parameters,X,T,state,noise) X = X + noise;[Y,状态]=模型(参数,X,状态);损失=交叉熵(Y,T);Gradients = dlgradient(损失,参数);结束

为了加速这个模型损失函数,转换输入噪音dlarray在求加速函数之前。因为modelLoss函数也支持金宝appdlarray对于噪声输入,不需要对函数进行更改。

噪音= dlarray(噪音,“SSCB”);accfun = dlaccelerate(@modelLoss);[loss,gradients,state] = dlfeval(accfun,parameters,X,T,state,noise);

或者,您可以加速模型损失函数中不需要随机输入的部分。

具有随机数生成的函数

在加速使用随机数生成的函数时必须小心,例如生成随机噪声并添加到输入中的函数。当软件缓存生成随机数的函数的跟踪时dlarray对象时,软件将在跟踪中缓存生成的随机样本。在重用跟踪时,加速函数使用缓存的随机样本。加速函数不会产生新的随机值。

使用随机数生成“喜欢”选项兰德函数使用dlarray对象支持加速。金宝app若要在加速函数中使用随机数生成,请确保该函数使用兰德函数与“喜欢”选项设置为跟踪dlarray对象(一个dlarray对象,它依赖于输入dlarray对象)。

例如,考虑下面的模型损失函数。

[loss,gradients,state] = modelLoss(parameters,X,T,state) sz = size(X);噪声= rand(sz);X = X +噪声;[Y,状态]=模型(参数,X,状态);损失=交叉熵(Y,T);Gradients = dlgradient(损失,参数);结束

以确保兰德函数为每个求值生成一个新值,请使用“喜欢”带有跟踪的选项dlarray对象X

[loss,gradients,state] = modelLoss(parameters,X,T,state) sz = size(X);噪声= rand(sz,“喜欢”, X);X = X +噪声;[Y,状态]=模型(参数,X);损失=交叉熵(Y,T);Gradients = dlgradient(损失,参数);结束

或者,您可以加速模型损失函数中不需要生成随机数的部分。

使用如果语句和循环

在加速使用如果语句和循环。特别是,当你用加速函数时,你会得到意想不到的结果如果语句或对于相同大小和格式的函数输入产生不同代码路径的循环。

加速函数如果语句或依赖于函数输入值或来自外部源的值(例如,随机数生成的结果)的循环条件可能导致意外行为。加速函数缓存新跟踪时,如果函数包含如果语句或方法给出的结果代码路径的跟踪如果语句或特定跟踪的循环条件。因为值的变化dlarray输入不会触发新的跟踪,当重用具有不同值的跟踪时,软件使用相同的缓存跟踪(包含相同的缓存代码路径),即使值的差异应该导致不同的代码路径。

通常,加速函数包含如果语句或循环的条件不依赖于函数输入值或外部因素(例如,遍历数组中的元素的循环)不会导致意外的行为。例如,因为大小的变化dlarray输入触发一个新的跟踪,当重用具有相同大小输入的跟踪时,该大小输入的缓存代码路径保持一致,即使值存在差异也是如此。

的代码路径来避免意外的行为如果语句,您可以重构代码,使其通过组合所有分支的结果并提取所需的解决方案来确定正确的结果。

例如,考虑以下代码。

如果tf Y = funcA(X);其他的Y = funcB(X);结束
要支持金宝app加速,可以用以下形式的代码替换它。
Y = tf*funcA(X) + ~tf*funcB(X);
或者,为了避免不必要的乘法操作,也可以使用此替换。
Y = cat(3,funcA(X),funcB(X));Y = Y(:,:,[tf ~tf]);
方法的两个分支中使用的代码都需要执行,因此这些技术可能会导致代码运行时间更长如果声明。

使用如果语句和循环依赖于dlarray对象的值,加速正文的如果语句或循环。

依赖句柄的函数输入

在加速以依赖句柄的对象作为输入的函数时,必须小心minibatchqueue具有指定为函数句柄的预处理函数的对象。的AcceleratedFunction对象在计算依赖句柄的输入函数时抛出错误。

相反,您可以加速模型损失函数中不需要依赖于句柄的输入的部分。

调试

在调试加速函数时必须小心。缓存的跟踪不支持断点。金宝app当使用加速函数时,软件只在跟踪过程中到达底层函数的断点。

要使用断点调试底层函数中的代码,请通过设置启用财产

属性来调试缓存的跟踪,可以将加速函数的输出与底层函数的输出进行比较CheckMode财产“宽容”

dlode45何时不支持加速金宝appGradientMode“直接”

dlaccelerate函数不支持加速金宝appdlode45函数,当GradientMode选择是“直接”.方法加速调用的代码dlode45函数,设置GradientMode选项“伴随”或加速未调用dlode45函数与GradientMode选项设置为“直接”

另请参阅

|||||

相关的话题