主要内容

手工定点转换的最佳实践

定点设计师™软件帮助你设计和算法转换为定点。你是否只是在MATLAB设计定点算法®或者使用定点设计师结合MathWorks®这些最佳实践代码生成产品,帮助你下载188bet金宝搏从通用MATLAB代码到一个有效的定点实现。这些最佳实践也覆盖在这个网络研讨会:手工定点转换网络研讨会的最佳实践

创建一个测试文件

构建代码的一个最佳实践是将从其他代码,你使用你的核心算法测试和验证结果。创建一个测试文件调用原始的MATLAB算法和定点版本的算法。例如,如下表所示,您可以设置一些输入数据融入到你的算法,然后,在你处理这些数据,创建一些情节来验证结果。因为你只需要转换定点算法部分,结构是更高效的代码,这样你有一个测试文件,你创造你的输入,打电话给你的算法,和阴谋的结果,和一个(或更多)算法的文件,在你的核心处理。

原始代码 最佳实践 修改后的代码
%测试输入x = randn (100 1);%算法y = 0(大小(x));y = x (1) (1);长度为n = 2: y (n) (x) = y (n - 1) + x (n);结束%验证结果yExpected = cumsum (x);情节(y-yExpected)标题(“错误”)

问题

生成测试输入和验证的结果是混合算法的代码。

修复

创建一个测试文件分开你的算法。把算法的函数。

测试文件

%测试输入x = randn (100 1);%算法y = cumulative_sum (x);%验证结果yExpected = cumsum (x);情节(y-yExpected)标题(“错误”)

算法的功能

函数y = cumulative_sum (x) y = 0(大小(x));y = x (1) (1);长度为n = 2: y (n) (x) = y (n - 1) + x (n);结束结束

您可以使用测试文件:

  • 验证您的浮点算法表现如你希望在你想把它转换成固定。浮点算法行为的基线,你比较你的算法的定点版本的行为。

  • 提出定点数据类型。

  • 比较的行为定点算法浮点基线版本。

你的测试文件应该行使算法对其完整的操作范围,以便模拟范围是准确的。例如,对于一个过滤器,现实的输入是脉冲,大笔的正弦曲线,线性调频信号。这些输入,使用线性理论,可以验证输出是正确的。信号产生最大输出可用于验证您的系统不溢出。提出的质量定点数据类型取决于算法的测试文件覆盖操作范围的准确性。

准备加速算法代码或代码生成

使用定点设计师,您可以:

  • 仪器代码并提供数据类型建议帮助你转换不动点算法,使用以下功能:

    • buildInstrumentedMex生成编译C代码,包括测井仪器。

    • showInstrumentationResults,显示检测结果记录,编译C代码。

    • clearInstrumentationResults从内存中清除记录仪器的结果。

  • 加速你的定点算法通过创建一个墨西哥人文件使用fiaccel函数。

任何你想要的MATLAB算法使用工具buildInstrumentedMex和任何你想要的定点算法加速使用fiaccel必须遵守代码生成的要求和规则。查看子集的MATLAB语言支持代码生成金宝app函数和对象支持C / c++代码生成金宝app

帮助你识别不支持的功能或结构在MATLAB代码金宝app中,使用以下工具之一。

  • 添加% # codegenMATLAB文件编译指示的。MATLAB代码分析器旗帜函数和构造在MATLAB语言的子集支持代码生成。金宝app这个建议似乎在实时在MATLAB中编辑您的代码编辑器。

    有关更多信息,请参见检查代码使用MATLAB代码分析器

  • 使用代码生成准备工具生成一个静态报告在你的代码。报告确定调用函数和使用不支持的数据类型代码生成。金宝app为一个函数,生成一份报告myFunction1在命令行输入coder.screener (“myFunction1”)

    有关更多信息,请参见使用代码生成校验码准备工具

检查定点支持函数中使用的算法金宝app

在你开始你的定点转换,确定哪些函数中使用不动点算法不支持。金宝app考虑如何更换或修改您的嵌入式目标的实现更优化。例如,您可能需要找到(或编写自己的)替代功能log2,fft,经验值。其他功能,如,因为,√6可能支持金宝app定点,但为了更好的效率,您可能想要考虑另一个实现一个查找表或CORDIC-based算法。

如果你不能找到一个立即更换,你可以继续将你其他的算法转换为定点通过绝缘功能,不支持任何定点与双输入,和演员回到定点类型输出。金宝app

原始代码 最佳实践 修改后的代码
y = 1 / exp (x);

问题

exp ()函数没有定义定点输入。

修复

把输入双直到你有一个替换。在这种情况下,1 / exp (x)更适合定点增长比吗exp (x),所以用一个替换整个表达式1 /经验功能,这可能是一个查找表。

y = 1 / exp(双(x));

管理数据类型和控制增长

(,)=语法被称为下标赋值。当你使用这个语法,MATLAB覆盖左边的值参数,但保留了现有数据类型和数组大小。这是特别重要的在保持定点变量不动点(而不是无意中把他们变成双打),和防止一些增长当你想保持一个特定的数据类型为输出。

原始代码 最佳实践 修改后的代码
acc = 0;为n = 1:元素个数(x) acc = acc + x (n);结束

问题

acc = acc + x (n)覆盖accacc + x (n)。当您使用的是双类型,这种行为很好。然而,当你介绍定点数据类型在你的代码中,如果acc的数据类型,覆盖吗acc可能会改变。

修复

保存的原始数据类型acc,分配到acc使用acc (,) =。使用下标赋值给眼睛水平值相同的数据类型acc和防止一些增长。

acc = 0;为n = 1:元素个数(x) acc (:) = acc + x (n);结束

有关更多信息,请参见控制一些增长

单独的数据类型定义的算法

仪表和代码生成,创建一个入口点函数,调用函数,您想要转换为定点。然后您可以把函数输入不同的数据类型。您可以添加调用不同的函数进行比较。通过使用一个入口点函数,您可以运行两个定点和浮点变量的算法。您还可以运行不同变体的定点。这种方法允许您更快速的遍历代码到达最优定点设计。

这种定点的方法转换为你更容易比较几种不同的定点实现,并允许您轻松gdp8 %你的算法不同的设备。

从你的算法单独的数据类型定义:

  1. 当一个变量是第一次定义,使用铸造(x,“喜欢”,y)0 (m, n,“喜欢”,y)丢给你所需的数据类型。

  2. 创建一个表的数据类型定义,从原来的代码中使用的数据类型。将定点之前,创建一个数据类型表,使用所有单一数据类型找到类型不匹配等问题。

  3. 运行代码连接到每个表,看看结果来验证连接。

原始代码 最佳实践 修改后的代码
%的算法n = 128;y = 0(大小(n));

问题

默认在MATLAB是双精度浮点数据类型。

修复

  1. 使用铸造(…,“喜欢”,…)0(…‘喜欢’,…)以编程方式指定一个单独的表中定义的类型。

  2. 创建一个原始类型表,通常在一个单独的功能。

  3. 单一数据类型添加到你的表来帮助验证与您的代码。

%的算法T = mytypes (“双”);n =投(128“喜欢”,T.n);y = 0(大小(n),“喜欢”,T.y);
函数T = mytypes (dt)开关(dt)情况下的双“T。双(n = []);T。双(y = []);“单一”T。n =单([]);T。y =单([]);结束结束

从算法代码分离数据类型规范使您能够:

  • 重用你的算法代码与不同的数据类型。

  • 保持你的算法与数据类型规范整洁和switch语句为不同的数据类型。

  • 改进算法代码的可读性。

  • 定点和浮点数据类型之间切换比较基线。

  • 定点设置之间切换变化不改变算法的代码。

转换为定点

你的目标转换成固定的点是什么?

在你开始转换之前,考虑你的目标转换成固定的点。你实现你的算法用C或HDL ?你的目标约束是什么?这些问题的答案确定等定点属性可用的字长,部分长度,和数学模式,以及可用的数学库。

构建和运行一个仪器的墨西哥人的功能

构建和运行一个仪器的墨西哥人定点类型建议使用函数buildInstrumentedMexshowInstrumentationResults功能。测试文件应该锻炼你的算法对其完整的操作范围。提出的质量定点数据类型取决于算法的测试文件涵盖了操作范围的准确性。一组简单的测试向量可能不锻炼的各种类型,所以使用建议作为指导原则选择一组初始的定点类型,并使用最好的判断和经验调整类型。如果循环指数只被作为索引变量,他们会自动转换成整数类型,所以您不必显式地将它们转换为定点。

算法代码 测试文件
函数[y, z] = myfilter (b, x, z) y = 0(大小(x));长度为n = 1: z (:) (x) = [x (n);z (1: end-1)];y (n) = b * z;结束结束
%测试输入b = fir1 (11, 0.25);t = linspace(0, 10 *π,256);x =罪((π/ 16)* t。^ 2);%线性啁啾z = 0(大小(b));%建立buildInstrumentedMex myfilter……args {b, x, z}直方图%运行[y, z] = myfilter_mex (b, x, z);%显示showInstrumentationResults myfilter_mex……-proposeFL -defaultDT numerictype (16)

创建一个类型表

创建一个类型表使用一个结构变量的原型。该类型的计算模拟运行。长与广泛的预期数据模拟运行产生更好的建议。您可以使用该类型或使用你的知识的算法和实现约束改善建议。

因为数据类型,而不是值,使用原型值指定为空([])。

在某些情况下,它可能是更有效的离开在浮点部分代码。例如,当有高动态范围或舍入错误代码是敏感的一部分。

算法代码 类型表 测试文件
函数[y, z] = myfilter (b, x, z, T) y = 0(大小(x),“喜欢”,T.y);长度为n = 1: z (:) (x) = [x (n);z (1: end-1)];y (n) = b * z;结束结束
函数T = mytypes (dt)开关dt '双“T。b =双([]);T。双(x = []);T。双(y = []);“fixed16”T。b = fi(15)[],真的,16日;T。x = fi([],真的,16日15);T。y = fi([],true,16,14); end end
%测试输入b = fir1 (11, 0.25);t = linspace(0, 10 *π,256);x =罪((π/ 16)* t。^ 2);%线性啁啾%把输入T = mytypes (“fixed16”);b =投(b,“喜欢”、肺结核);x =投(x,“喜欢”,T.x);z = 0(大小(b”),“像”,T.x);% [y, z] = myfilter运行(b, x, z, T);

运行与定点类型和比较结果

创建一个测试文件验证浮点算法是将它转换为定点之前预期。您可以使用相同的测试文件提出定点数据类型,并比较定点结果后的浮点基准转换。

优化数据类型

使用缩放双打

使用缩放双打来检测潜在的溢出。比例之间混合双打浮点和定点数字。定点设计师将它们存储在双打的缩放、标志和字长信息保留。使用缩放双打,您可以使用数据类型覆盖(DTO)财产或者你可以设置“数据类型”财产“ScaledDouble”finumerictype构造函数。

…… 使用…… 例子

在本地设置数据类型覆盖

numerictype数据类型财产

T。= fi([], 1, 16日13日“数据类型”,“ScaledDouble”);=投(π,“喜欢”T.a)
= 3.1416 DataTypeMode:双扩展:二进制扩展Signedness:签了字:16 FractionLength: 13

设置数据类型覆盖全球

fiprefDataTypeOverride财产

fipref (“DataTypeOverride”,“ScaledDoubles”)T。一个= fi(13)[], 16日;
= 3.1416 DataTypeMode:双扩展:二进制扩展Signedness:签了字:16 FractionLength: 13

有关更多信息,请参见按比例缩小的双打

使用直方图来调整数据类型设置

调整定点类型设置、运行buildInstrumentedMex函数与柱状图国旗,然后运行生成的墨西哥人与你想要的测试输入功能。当你使用showInstrumentationResults显示代码生成报告,报告显示一个直方图图标。点击图标打开NumericTypeScope和视图观察值的分布仿真为选定的变量。

溢出显示红色代码生成报告显示在“范围”之外本NumericTypeScope。发射的NumericTypeScope相关变量或表达式通过单击直方图视图图标

探索设计权衡

一旦你有了第一组定点数据类型,您可以添加不同的定点值类型表。您可以修改和重复,避免溢出,调整部分的长度,改变舍入方法消除偏见。

算法代码 类型表 测试文件
函数[y, z] = myfilter (b, x, z, T) y = 0(大小(x),“喜欢”,T.y);n = 1:长度(x) z (:) = [x (n);z (1: end-1)];y (n) = b * z;结束结束
函数T = mytypes (dt)开关dt情况下“双”T。b =双([]);T。双(x = []);T。双(y = []);情况下“fixed8”T。b = fi([],真的,8,7);T。x = fi([],真的,8,7);T。y = fi(6)[],真的,8日;情况下“fixed16”T。b = fi(15)[],真的,16日;T。x = fi([],真的,16日15);T。y = fi(14)[],真的,16日;结束结束
函数mytest%测试输入0.25 b = fir1(11日);t = linspace(0, 10 *π,256);x =罪((π/ 16)* t。^ 2);%线性啁啾运行%y0 =入口点(“双”x、b);日元=入口点(“fixed8”x、b);造成=入口点(“fixed16”x、b);%的阴谋次要情节(1,1)情节(t, x,“c”t y0,“k”)传说(“输入”,“基准输出”)标题(“基线”次要情节(3 2 3)情节(t,日元,“k”)标题(“8位定点输出”次要情节(3、2、4)情节(t, y0-double(日元)“r”)标题(“8位定点误差”次要情节(3 2 5)情节(t,造成,“k”)标题(的16位定点输出)包含(“时间(s)”次要情节(3 2 6)情节(t, y0-double(造成),“r”)标题(的16位定点误差)包含(“时间(s)”)结束
函数[y, z] =入口点(dt, b, x) T = mytypes (dt);b =投(b,“喜欢”、肺结核);x =投(x,“喜欢”,T.x);z = 0(大小(b),“喜欢”,T.x);[y, z] = myfilter (b, x, z, T);结束

优化算法

使用fimath自然类型C或高密度脂蛋白

fimath属性定义的规则执行算术运算fi对象,包括数学、舍入和溢出的属性。您可以使用fimathProductModeSumMode保留自然属性的数据类型C和高密度脂蛋白。的KeepLSB设置ProductModeSumMode模型的行为整数操作在C语言中,KeepMSB许多DSP设备的行为模型。不同的舍入方法代码需要不同数量的开销。设置RoundingMethod财产地板上,相当于二进制补码截断,提供最有效的舍入的实现。同样,标准的方法来处理溢出是包装使用模运算。其他溢出处理方法创建昂贵的逻辑。只要有可能,设置OverflowAction包装

MATLAB代码 最佳实践 生成的C代码
%代码被编译函数y =加法器(a, b) y = a + b;结束与类型定义默认fimath设置:T。= fi([], 1, 16日0);T。b = fi ([], 1, 0);一个=(0,“喜欢”,T.a);b =投(0,“喜欢”、肺结核);

问题

额外的代码生成实现饱和溢出,最近的舍入,不能算数。

整数加法器(短,短b) {int y;int我;int i1;int i2;int i3;我=;i1 = b;如果((& 65536)! = 0){i2 =我| -65536;其他}{i2 =我& 65535;}如果((i1 & 65536) ! = 0) {i3 = i1 | -65536; } else { i3 = i1 & 65535; } i = i2 + i3; if ((i & 65536) != 0) { y = i | -65536; } else { y = i & 65535; } return y; }

代码被编译

函数y =加法器(a, b) y = a + b;结束

与类型定义fimath设置匹配您的处理器类型:

F = fimath (…“RoundingMethod”,“地板”,…‘OverflowAction’,‘包装’,……“ProductMode”、“KeepLSB’,……“ProductWordLength”, 32岁的……“SumMode”、“KeepLSB’,……“SumWordLength”、32);T。= fi([], 1, 16日0时,F);T。b = fi([],1,16,0,F); a = cast(0,'like',T.a); b = cast(0,'like',T.b);

修复

使生成的代码更高效,选择定点数学设置匹配您的处理器类型。

整数加法器(短,短b){返回a + b;}

用更有效的定点实现替换内置函数

一些MATLAB内置函数可以更高效的为定点实现。例如,你可以换一个内置函数与一个查找表实现,或CORDIC的实现,只需要迭代shift-add操作。

在可能的情况下重新实现部门操作

通常,部门不完全支持硬件和可能导致缓慢的处理。金宝app当你的算法需要一个部门,考虑换成以下选项之一:

  • 使用移位当分母是2的幂。例如,bitsra (x, 3)而不是x / 8

  • 乘以逆当分母是恒定的。例如,x * 0.2而不是x / 5

消除浮点变量

为更高效的代码,消除浮点变量。一个例外是循环指数,因为他们通常成为整数类型。