如何在 MATLAB 中编写向量化函数

2024-04-14

我刚刚学习MATLAB,我发现很难理解循环与矢量化函数的性能因素。

在我之前的问题中:MATLAB 中的嵌套 for 循环非常慢(预分配) https://stackoverflow.com/q/7811239/518169我意识到使用向量化函数与 4 个嵌套循环相比运行时间相差 7 倍.

在该示例中,无需循环遍历 4 维数组的所有维度并计算每个向量的中值,而是直接调用中位数(stack,n)(其中 n 表示中值函数的工作维度)更干净、更快。

但中位数只是一个非常简单的例子我只是幸运它有这个实施尺寸参数.

我的问题是您如何自己编写一个函数,使其与实现此维度范围的函数一样高效?

例如你有一个函数my_median_1D它仅适用于一维向量并返回一个数字。

你如何写一个函数my_median_nD它的作用类似于 MATLAB 的中值,通过采用一个 n 维数组和一个“工作尺寸”范围?

Update

我找到了计算高维中位数的代码

% In all other cases, use linear indexing to determine exact location
% of medians.  Use linear indices to extract medians, then reshape at
% end to appropriate size.
cumSize = cumprod(s);
total = cumSize(end);            % Equivalent to NUMEL(x)
numMedians = total / nCompare;

numConseq = cumSize(dim - 1);    % Number of consecutive indices
increment = cumSize(dim);        % Gap between runs of indices
ixMedians = 1;

y = repmat(x(1),numMedians,1);   % Preallocate appropriate type

% Nested FOR loop tracks down medians by their indices.
for seqIndex = 1:increment:total
  for consIndex = half*numConseq:(half+1)*numConseq-1
    absIndex = seqIndex + consIndex;
    y(ixMedians) = x(absIndex);
    ixMedians = ixMedians + 1;
  end
end

% Average in second value if n is even
if 2*half == nCompare
  ixMedians = 1;
  for seqIndex = 1:increment:total
    for consIndex = (half-1)*numConseq:half*numConseq-1
      absIndex = seqIndex + consIndex;
      y(ixMedians) = meanof(x(absIndex),y(ixMedians));
      ixMedians = ixMedians + 1;
    end
  end
end

% Check last indices for NaN
ixMedians = 1;
for seqIndex = 1:increment:total
  for consIndex = (nCompare-1)*numConseq:nCompare*numConseq-1
    absIndex = seqIndex + consIndex;
    if isnan(x(absIndex))
      y(ixMedians) = NaN;
    end
    ixMedians = ixMedians + 1;
  end
end

你能向我解释一下吗与简单的嵌套循环相比,为什么此代码如此有效?就像其他函数一样,它具有嵌套循环。

我不明白怎么可能快 7 倍还有,那为什么这么复杂.

Update 2

我意识到使用中位数不是一个很好的例子,因为它本身就是一个复杂的函数,需要对数组进行排序或其他巧妙的技巧。我用平均值重新进行了测试,结果更加疯狂:19 秒 vs 0.12 秒。这意味着内置的 sum 方法比嵌套循环快 160 倍.

我真的很难理解一种行业领先的语言如何根据编程风格而具有如此极端的性能差异,但我看到了下面答案中提到的几点。


Update 2 (解决您更新的问题)

MATLAB 经过优化,可以很好地处理数组。一旦您习惯了它,只需键入一行并让 MATLAB 自行完成完整的 4D 循环工作,而无需担心它,这实际上非常好。 MATLAB 通常用于原型设计/一次性计算,因此为人员编码节省时间并放弃 C[++|#] 的一些灵活性是有意义的。

这就是为什么MATLAB 内部做了some循环得很好- 通常将它们编码为编译函数。

您给出的代码片段并不真正包含执行主要工作的相关代码行,即

% Sort along given dimension
x = sort(x,dim);

换句话说,您显示的代码只需要通过现在排序的多维数组中的正确索引来访问中值x(这并不需要太多时间)。访问所有数组元素的实际工作是通过sort,这是一个内置(即编译和高度优化的)函数。

原答案 (关于如何构建自己的在数组上工作的快速函数)

实际上有很多内置函数采用维度参数:min(stack, [], n), max(stack, [], n), mean(stack, n), std(stack, [], n), median(stack,n), sum(stack, n)...以及其他内置函数(例如exp(), sin()自动处理整个数组的每个元素(即sin(stack)自动为您执行四个嵌套循环,如果stack是 4D),您可以构建许多您可能需要的功能,只需依赖现有的内置函数.

如果这对于特定情况还不够,您应该看看repmat http://www.mathworks.de/help/techdoc/ref/repmat.html, bsxfun http://www.mathworks.de/help/techdoc/ref/bsxfun.html, arrayfun http://www.mathworks.de/help/techdoc/ref/arrayfun.html and accumarray http://www.mathworks.de/help/techdoc/ref/accumarray.html这些是非常强大的函数,可以“以 MATLAB 方式”执行操作。只需在 SO 上搜索问题(或者更确切地说是答案)using https://stackoverflow.com/search?q=%5Bmatlab%5D%20repmat one https://stackoverflow.com/search?q=%5Bmatlab%5D%20bsxfun of https://stackoverflow.com/search?q=%5Bmatlab%5D%20arrayfun these https://stackoverflow.com/search?q=%5Bmatlab%5D%20accumarray,通过这种方式,我学到了很多关于 MATLAB 的优点。

As an example,假设您想实施p-norm http://en.wikipedia.org/wiki/Norm_%28mathematics%29#p-norm沿维度的堆栈n,你可以写

function result=pnorm(stack, p, n)
result=sum(stack.^p,n)^(1/p);

...您可以有效地重用“哪个维度的能力”sum.

Update

正如马克斯在评论中指出的那样,还可以看看冒号运算符 (:) http://www.mathworks.de/help/techdoc/ref/colon.html这是一个非常强大的工具,用于从数组中选择元素(甚至改变它的形状,这通常是通过reshape http://www.mathworks.de/help/techdoc/ref/reshape.html).

一般来说,看看这个部分数组运算 http://www.mathworks.de/help/techdoc/ref/f16-5872.html#f16-55525在帮助中 - 它包含repmat等人。上面提到了,而且还cumsum以及一些更晦涩的辅助函数,您应该将其用作构建块。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 MATLAB 中编写向量化函数 的相关文章

  • 编译器处理包含保护头的开销有多大?

    为了加速大型源文件的编译 修剪翻译单元中使用的标头数量是否更有意义 或者编译代码的成本是否远远超过处理包含保护的时间标头 如果后者是真的 那么工程工作最好花在创建更多 轻量级的标头上 而不是更少 那么 现代编译器需要多长时间才能处理有效包含
  • 有没有办法在 MATLAB 中执行函数内联?

    我可以使用什么语言功能或开箱即用的技巧来完成 MATLAB 中的函数内联 令人烦恼的是 Google 搜索 matlab 内联函数 http www google com search q matlab inline function揭示了
  • 如何从 .NET DataGridView 控件单元格值写入文本文件?

    我有以下代码应该循环遍历我的所有行DataGridView 并将其所有单元格值写入文本文件 但是 它输出所有行 但仅输出每行的第一个单元格 而不输出其他三个单元格 string file name C test1 txt var objWr
  • 递归和迭代的速度性能 – 为什么它们对于不同的“小”数都以相同的速度运行?

    我正在尝试优化我拥有的代码 为了做到这一点 我编写了这段代码来查看递归与迭代的效果 该代码 计数 到 10 的 n 次方 public Form1 InitializeComponent Stopwatch sw new Stopwatch
  • 带有 return 语句的 Julia @parallel for 循环

    如何在满足条件时立即返回所有工作人员的函数中编写并行 for 循环 IE 像这样的东西 function test n sync parallel for i in 1 1000 statement if condition return
  • 按顺序范围循环映射

    我正在寻找一种确定的方法来范围Go map为了 Go 规范 https golang org ref spec For statements陈述如下 映射的迭代顺序未指定 并且不保证从一次迭代到下一次迭代的顺序相同 如果在迭代过程中删除尚未
  • 为什么这个 C++ 包装类没有被内联掉?

    EDIT 我的构建系统出了问题 我还在弄清楚到底是什么 但是gcc产生了奇怪的结果 尽管它是 cpp文件 但是一旦我使用了g 然后它按预期工作 对于我一直遇到麻烦的事情来说 这是一个非常精简的测试用例 其中使用数字包装类 我认为会内联 使我
  • Python 请求与 PyCurl 性能

    Requests 库与 PyCurl 的性能相比如何 我的理解是 Requests 是 urllib 的 python 包装器 而 PyCurl 是本机 libcurl 的 python 包装器 因此 PyCurl 应该获得更好的性能 但不
  • 在 MATLAB 中高效地形成动态窗口

    有人可以帮助我提供一种有效的方法 或者帮助我执行提供的代码 以尽可能少的步骤获得相同的结果 我将感激你 我有一个原始数组 A 1 1 1 4 3 4 5 4 4 3 3 1 0 0 2 6 2 6 3 6 6 2 7 4 8 7 2 2 2
  • 计算 IOrderedEnumerable 的数量而不消耗它

    我想做的 简短版本 var source new 2 4 6 1 9 OrderBy x gt x int count source Count lt get the number of elements without performin
  • 使用 lsqcurvefit 进行拟合

    我想将一些数据拟合到洛伦兹函数 但当我使用不同数量级的参数时 我发现拟合存在问题 这是我的洛伦兹函数 function value lorentz x x0 gamma amp value amp gamma 2 x x0 2 gamma
  • 相当于使用 for-loop 代替 do-while-loop

    我想知道 c 中等效的 for 循环或任何其他循环组合是什么 而不是使用 do while 循环 任何类型的循环都可以通过无限 永远 循环和条件循环的组合来构造break陈述 例如 要转换 do
  • 发送 WCF 消息在负载下延迟

    当从自托管 WCF 服务向许多客户端 大约 10 个左右 发送消息时 有时消息的延迟时间比我预期的要长得多 发送到本地网络上的客户端需要几秒钟 有谁知道为什么会这样以及如何解决它 一些背景 该应用程序是股票行情式服务 它从第三方服务器接收消
  • MATLAB:生成给定三种颜色的颜色图

    我正在尝试在 MATLAB 中生成给定三种颜色 最高值 零值和最低值 的颜色图 我的思维过程是从最高端到中间循环 并将每个步骤存储到一个 3xN 第一列是 R 第二列是 G 第三列是 B 矩阵 所以我正在使用 fade from high
  • 带 if 语句的可向量化 FIND 函数 MATLAB

    我有一个矩阵u 我想遍历所有行和所有列并执行以下操作 如果元素非零 我返回行索引的值 如果元素为零 则查找该元素之后的下一个非零元素的行索引 我可以使用两个带有 find 函数的 for 循环轻松完成此操作 但我需要多次执行此操作 不是因为
  • 浮点转换和性能

    我知道在浮点数和整数之间进行转换时可能会出现错误 但是性能如何 请忽略准确性问题 一般来说 如果我对不同算术类型的操作数 即不同的浮点类型 例如 float and double 和浮点 整数类型组合 例如float and int 是否存
  • 在 C# 中创建文件的最快方法

    我正在运行一个程序来测试在包含大量文件的文件夹中查找和迭代所有文件的速度 该过程中最慢的部分是创建超过 100 万个文件 我目前正在使用一种非常幼稚的方法来创建文件 Console Write Creating 0 N0 file s of
  • Windows 10 Fall Creators Update (1709) 后,log4net 处理呼叫者位置信息变得非常慢

    我知道 log4net 的文档指出 记录调用者位置信息可能非常慢 除非软件的性能不受影响 否则不应使用 在 Windows 10 秋季创意者更新之前 情况都是如此 这是一个小示例项目 应用程序配置
  • 如何在Matlab脚本中将泰勒级数系数存储到数组中

    这个问题是在 m 脚本的上下文中 我知道如何获取函数的泰勒级数 但我没有看到任何命令允许将级数的系数存储到数组中 sym2poly似乎不起作用 如何将系数存储到数组中 例如这个函数 syms x f 1 x 2 4 x 9 我们怎样才能得到
  • 在 Postgres 9.0+ 中使用 PL/pgSQL 循环表

    我想循环遍历所有表以计算每个表中的行数 以下查询给我一个错误 DO DECLARE tables CURSOR FOR SELECT tablename FROM pg tables WHERE tablename NOT LIKE pg

随机推荐

  • 从 AOSP master 切换到 froyo

    我刚刚用 repo 检查了 master 现在我想改用froyo 我怎样才能做到这一点而不需要再次下载一堆东西 我不想再次下载一堆东西 我只是希望能够像普通的 git 克隆一样在分支之间自由移动 由于您使用 repo 下载了所有内容 因此您
  • 迭代 EnumMap#entrySet

    枚举结束Map entrySet对于所有 Map 实现 特别是 EnumMap 不能按预期工作 IdentityHashMap这是 Josh Bloch 的示例代码谜题演示 谜题 5 http strangeloop2010 com sys
  • 一次热编码期间出现 RunTimeError

    我有一个数据集 其中类值以 1 步从 2 到 2 i e 2 1 0 1 2 其中 9 标识未标记的数据 使用一种热编码 self one hot encode labels 我收到以下错误 RuntimeError index 1 is
  • Python:第二个for循环未运行

    scores surfers results f open results txt for each line in results f name score each line split scores append float scor
  • __attribute__ 是否适用于声明中的所有变量?

    是否 attribute 指令适用于在一行中声明的所有成员 int a b c 声明三个 int 变量 int a b c 将变量 a 声明为 int 指针 将 b 和 c 声明为 int int attribute used a b c
  • 如何检测 firebase firestore 数据库中的实时侦听器错误?

    火库听众 https firebase google com docs firestore query data listen将在一段时间后随机关闭 可能是由于不活动 并且在 python 中没有简单的方法来捕获它们抛出的错误 因为它们将它
  • 我需要 T-SQL 中的国家/地区列表

    我有一个国家 地区表 其中包含国家 地区名称列 我需要 DDL 中现成的列表来填充 CountryName 列 该表驻留在 SQL Server 2008 中 你可以尝试这个脚本 CREATE TABLE tbl Countries Cou
  • 使用 D3.js 单击切换图例时重绘堆栈条形图

    我想使用 D3 js 实现带有切换图例的堆栈栏 单击图例时 堆栈栏应重新绘制 如果图例处于活动状态 则与图例对应的矩形板应消失 反之亦然 单击图例时 我无法正确更新与组元素和组元素内存在的矩形元素绑定的数据 在 DOM 树中 单击图例 矩形
  • c# protobuf-net反序列化时某些属性值始终为-1

    在我没有注意到这一点之前 我不确定这个问题是否是错误 或者只是这个 我创建一个Document类并声明 protobuf net 限制 ProtoContract public class Document ProtoMember 1 pr
  • 打开本地项目钥匙串?

    有谁知道如何打开本地物品钥匙串 小牛队的新功能 SecKeychainOpen 我希望能够请求用户允许使用该钥匙串中的某些条目进行访问SecKeychainFindInternetPassword 例如对于您调用的系统钥匙串SecKeych
  • 如何使用“typedef NS_ENUM”在一个 .h 文件中定义多个变量类型

    我用过typedef NS ENUM重新组织旧代码中的数据常量 使用方法在这里找到 https stackoverflow com a 42009056 2348597 every typedef被声明在一个单一的 h可以导入到项目中任何类
  • Rails 会话中存储的对象变成了字符串?

    通常我不会在 Rails 会话中存储对象 但我正在使用需要此功能的库 我遇到了一个非常奇怪的问题 其中存储的对象在重定向后显示为字符串 为了重现 我创建了一个示例 Rails 4 1 应用程序 rails new session test
  • 如何编写从配置文件中获取值的自定义正则表达式验证器?

    我必须在模型中对用户名属性使用正则表达式验证器 我从配置文件中获取这个正则表达式 RegularExpression UsernameValidationExpression UsernameValidationExpression val
  • 如何在打字中安装express?

    我正在尝试在我的应用程序中使用expressjs 安装后使用typings install express ambient save I run tsc 但我收到两个错误 types main ambient express index d
  • 使用 OpenCV 对非正面图像进行人脸检测

    我正在尝试使用 opencv 来检测人脸 脸部不是正面 相机从侧面拍摄脸部 因此只能看到一只眼睛和部分嘴巴 我尝试了具有多种配置的 HaarDetectObjects 但没有获得任何好处 我改变了级联并进行了测试 haarcascade f
  • 在折线图中的特定点添加标记

    我正在绘制一个绘图线图 并希望使用标记突出显示线图上的特定点 其中数据框中的另一列不是 NA 此外 当我将鼠标悬停在绘图上时 我只想查看位于标记点上的 y 值 而不是绘图的其余部分 这是一个可重现的示例 到目前为止我已经尝试做到这一点 li
  • 使用 Python 检测 OpenCV 中的线条和形状

    我一直在使用 OpenCV cv2 并检测线条和形状 假设我女儿画了一幅图画 如下所示 我正在尝试编写一个Python脚本来分析绘图并将其转换为硬线条 形状 例如 话虽这么说 我已经安装了 opencv 并尝试使用它 但除了能够在图像中绘制
  • 如何设置扭曲的日志记录级别?

    我正在使用带有twisted的autobahn包 它会在每次连接到websocket时显示调试消息 我尝试将日志记录级别切换为信息但没有成功 import logging logging basicConfig level logging
  • 如何通过 Java 运行我的 haskell 函数

    假设我有一个 haskell 函数add in math hs 我怎样才能运行add通过Java程序运行函数并将输出存储为变量 也许像下面这样 public int runHaskell String haskellFile int out
  • 如何在 MATLAB 中编写向量化函数

    我刚刚学习MATLAB 我发现很难理解循环与矢量化函数的性能因素 在我之前的问题中 MATLAB 中的嵌套 for 循环非常慢 预分配 https stackoverflow com q 7811239 518169我意识到使用向量化函数与