为什么矢量化 numpy 代码比 for 循环慢?

2024-01-09

我有两个 numpy 数组,X and Y,有形状(n,d) and (m,d), 分别。假设我们要计算每行之间的欧几里得距离X和每一行Y并将结果存储在数组中Z有形状(n,m)。我对此有两个实现。第一个实现使用两个 for 循环,如下所示:

for i in range(n):
      for j in range(m):
        Z[i,j] = np.sqrt(np.sum(np.square(X[i] - Y[j])))

第二种实现仅通过矢量化使用一个循环:

for i in range(n):
      Z[i] = np.sqrt(np.sum(np.square(X[i]-Y), axis=1))

当我在特定的机器上运行这些代码时X and Y数据显示,第一次实现耗时近30秒,第二次实现耗时近60秒。我预计第二个实现会更快,因为它使用矢量化。其运行缓慢的原因是什么?我知道我们可以通过完全矢量化代码来获得更快的实现,但我不明白为什么第二个代码(部分矢量化)比非矢量化版本慢。

这是完整的代码:

n,m,d = 5000,500,3000
X = np.random.rand(n,d)
Y = np.random.rand(m,d)
Z = np.zeros((n,m))

tic = time.time()
for i in range(n):
      for j in range(m):
        Z[i,j] = np.sqrt(np.sum(np.square(X[i] - Y[j])))
print('Elapsed time 1: ', time.time()-tic)

tic = time.time()
for i in range(n):
      Z[i] = np.sqrt(np.sum(np.square(X[i]-Y), axis=1))
print('Elapsed time 2: ', time.time()-tic)


tic = time.time()
train_squared = np.square(X).sum(axis=1).reshape((1,n))
test_squared = np.square(Y).sum(axis=1).reshape((m,1))
test_train = -2*np.matmul(Y, X.T)
dists = np.sqrt(test_train + train_squared + test_squared)
print('Elapsed time 3: ', time.time()-tic)

这是输出:

Elapsed time 1:  35.659096002578735
Elapsed time 2:  65.57051086425781
Elapsed time 3:  0.3912069797515869

我拆解了你的方程并将其简化为这个MVCE https://stackoverflow.com/help/mcve:

for i in range(n):
    for j in range(m):
        Y[j].copy()

for i in range(n):
    Y.copy()

The copy()这里只是为了模拟减法X。减法本身应该相当便宜。

这是我电脑上的结果:

  • 第一个花了 10 毫秒。
  • 第二个花了13秒!

我正在复制完全相同数量的数据。使用您的选择n=5000, m=500, d=3000,这段代码正在复制60GB数据的。

说实话,我对这13秒并不感到惊讶。这已经超过 4GB/s,基本上是我的 CPU 和 RAM 之间的最大带宽(例如memcpy).

真正令人惊讶的是,第一次测试仅用了 0.01 秒就复制了 60GB,这意味着 6TB/s!

我很确定这是因为数据实际上根本没有离开 CPU。它只是在 CPU 和 L1 缓存之间来回切换:3000 个双精度数字的数组可以轻松放入 32KiB L1 缓存中。

因此,我推断你的第二个算法不如人们天真的期望的主要原因是因为处理一整块500×3000每次迭代的元素对 CPU 缓存非常不友好:您基本上将整个缓存移入 RAM!相反,您的第一个算法确实在某种程度上利用了缓存,因为3000到时元素仍将在缓存中sum进行计算,因此 CPU 和 RAM 之间移动的数据量几乎没有那么多。 (一旦你有了总和,3000元素数组被“丢弃”,这意味着它可能只会在缓存中被覆盖,而永远不会返回到实际的 RAM。)


当然,进行矩阵乘法要快得多,因为您的问题本质上是以下形式:

C[i, j] = ∑[k] f(A[i, k], B[j, k])

如果你更换f(x, y) with x * y,你可以看到它只是矩阵乘法的一种变体。操作f这里并不是非常重要 - 重要的是索引在这个方程中的表现,它决定了数组如何存储在内存中。矩阵乘法算法的本质在于能够通过blocking,因此原则上,即使对于用户定义的算法,整体算法也不会发生显着变化f。不幸的是,在practice支持用户定义操作的库很少,所以你必须使用这个技巧(X - Y)**2 = X**2 - 2 X Y + Y**2正如你所做的那样。但它完成了工作:D

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

为什么矢量化 numpy 代码比 for 循环慢? 的相关文章

  • 如何检查python xlrd库中的excel文件是否有效

    有什么办法与xlrd库来检查您使用的文件是否是有效的 Excel 文件 我知道还有其他库可以检查文件头 我可以使用文件扩展名检查 但为了多平台性我想知道是否有任何我可以使用的功能xlrd库本身在尝试打开文件时可能会返回类似 false 的内
  • 如何在Python中同时运行两只乌龟?

    我试图让两只乌龟一起移动 而不是一只接着另一只移动 例如 a turtle Turtle b turtle Turtle a forward 100 b forward 100 但这只能让他们一前一后地移动 有没有办法让它们同时移动 有没有
  • pyspark 数据框中的自定义排序

    是否有推荐的方法在 pyspark 中实现分类数据的自定义排序 我理想地寻找 pandas 分类数据类型提供的功能 因此 给定一个数据集Speed列 可能的选项是 Super Fast Fast Medium Slow 我想实现适合上下文的
  • 工作日重新订购 Pandas 系列

    使用 Pandas 我提取了一个 CSV 文件 然后创建了一系列数据来找出一周中哪几天崩溃最多 crashes by day bc DAY OF WEEK value counts 然后我将其绘制出来 但当然它按照与该系列相同的排名顺序绘制
  • sklearn 中的 pca.inverse_transform

    将我的数据拟合后 X 我的数据 pca PCA n components 1 pca fit X X pca pca fit transform X 现在 X pca 具有一维 当我根据定义执行逆变换时 它不是应该返回原始数据 即 X 二维
  • 如果未引发异常,则通过 Python 单元测试

    在Python中unittest框架 是否有一种方法可以在未引发异常的情况下通过单元测试 否则会因 AssertRaise 而失败 如果我正确理解你的问题 你could做这样的事情 def test does not raise on va
  • 如何在 Python 中加密并在 Java 中解密?

    我正在尝试在 Python 程序中加密一些数据并将其保存 然后在 Java 程序中解密该数据 在Python中 我像这样加密它 from Crypto Cipher import AES KEY 1234567890123456789012
  • Keras:如何保存模型或权重?

    如果这个问题看起来很简单 我很抱歉 但是阅读 Keras 保存和恢复帮助页面 https www tensorflow org beta tutorials keras save and restore models https www t
  • 结构差异 sudo() run('sudo 命令')

    我想知道函数之间有什么区别sudo 和函数run sudo u user smth 文档上有 sudo 在所有运行方式上都是相同的 除了它总是换行 调用 sudo 程序中的给定命令以提供超级用户 特权 但有几次 sudo cmd 提示我输入
  • 在 Windows 上使用 apache mod_wsgi 运行 Flask 应用程序时导入冲突

    我允许您询问我在 Windows 上使用您的 mod wsgi portage 托管 Flask 应用程序时遇到的问题 我有两个烧瓶应用程序 由于导入冲突 只有一个可以同时存在 IE 如果请求申请 1 我有回复 然后 如果我请求应用程序 2
  • .pyx 文件出现未知文件类型错误

    我正在尝试构建一个包含 pyx 文件的 Python 包 pyregion 但在构建过程中出现错误 检查以下输出 python setup py build running build running build py creating b
  • 通过索引访问Python字典的元素

    考虑一个像这样的字典 mydict Apple American 16 Mexican 10 Chinese 5 Grapes Arabian 25 Indian 20 例如 我如何访问该字典的特定元素 例如 我想在对 Apple 的第一个
  • Jython 和 SAX 解析器:允许的实体不超过 64000 个?

    我做了一个简单的测试xml saxJython 中的解析器在处理大型 XML 文件 800 MB 时遇到以下错误 Traceback most recent call last File src project xmltools py li
  • Python:IndexError:修改代码后列表索引超出范围

    我的代码应该提供以下格式的输出 我尝试修改代码 但我破坏了它 import pandas as pd from bs4 import BeautifulSoup as bs from selenium import webdriver im
  • ANTLR 获取并拆分词法分析器内容

    首先 对我的英语感到抱歉 我还在学习 我为我的框架编写 Python 模块 用于解析 CSS 文件 我尝试了 regex ply python 词法分析器和解析器 但我发现自己在 ANTLR 中 第一次尝试 我需要解析 CSS 文件中的注释
  • 使用“默认”环境变量启动新的子进程

    我正在编写一个构建脚本来解析依赖的共享库 及其共享库等 这些共享库在正常情况下是不存在的PATH环境变量 为了使构建过程正常工作 让编译器找到这些库 PATH已更改为包含这些库的目录 构建过程是这样的 加载器脚本 更改 PATH gt 基于
  • 从 NumPy 数组到 Mat 的 C++ 转换 (OpenCV)

    我正在围绕 ArUco 增强现实库 基于 OpenCV 编写一个薄包装器 我试图构建的界面非常简单 Python 将图像传递给 C 代码 C 代码检测标记并将其位置和其他信息作为字典元组返回给 Python 但是 我不知道如何在 Pytho
  • Elasticsearch 通过搜索返回拼音标记

    我用语音分析插件 https www elastic co guide en elasticsearch plugins current analysis phonetic html由于语音转换 从弹性搜索中进行一些字符串匹配 我的问题是
  • python 线程安全可变对象复制

    Is 蟒蛇的copy http docs python org 2 library copy html模块线程安全吗 如果不是 我应该如何在 python 中以线程安全的方式复制 deepcopy 可变对象 蟒蛇的GIL http en w
  • Apache Beam Pipeline 写表后查询表

    我有一个 Apache Beam Dataflow 管道 它将结果写入 BigQuery 表 然后我想查询该表以获取管道的单独部分 但是 我似乎无法弄清楚如何正确设置此管道依赖性 我编写的新表 然后想要查询 与一个单独的表连接以进行某些过滤

随机推荐

  • 从 html 中的交互式表格更新绘图

    我想做的是在 html 中过滤后根据 DT 表的输出更新绘图 例如 这是过滤表的屏幕截图maz在 HTML 中 我希望散点图更新为仅显示过滤表中显示的值 这可能吗 我知道我可以使用闪亮的网络应用程序 https www shinyapps
  • 如何配置 AWS Athena 结果的文件格式

    目前 Athena 查询结果在 S3 中为 tsv 格式 有没有办法配置 Athena 查询以返回 Parquet 格式的结果 Answer 目前无法直接与 Athena 进行此操作 在配置 Athena 查询结果时 您只能设置查询结果位置
  • 节点与C应用程序之间的进程间通信

    我有 2 个软件组件 我想互相交谈 一个 Node js Web 应用程序 用 C 编写的专用服务器 一段相当简单的代码 处理一些我不想为其他语言包装的晦涩库 我想要的对话非常简单 节点 设置资源 ID A C 应用程序 好的 这是参考号
  • FACEBOOK GRAPH/rest api:如何登录我自己的用户以使用 PHP 更新我的状态

    我想在 Facebook 图形 API 的帮助下通过 PHP 更新粉丝专页的状态 谷歌说 不起作用 现在我想通过PHP更新我自己的用户状态 我的主要问题是如何将我自己的用户登录到图形 api 使用 PHP 而不使用浏览器 也没有有趣的 PH
  • 配置:错误:leptonica 库丢失(在 MinGW 上构建 tesseract-ocr-3.01 时)

    运行配置时失败 checking for leptonica yes checking for pixCreate in llept no configure error leptonica library missing 但我已经构建了l
  • 如何使用 Javascript 或 jQuery 取消选择文本?

    我有一个可拖动 jQuery UI 元素 上面有 取消 文本 这就是我的意思 main draggable cancel main gt start function deselect text 当我拖动元素时 我经常会意外选择文本 我想在
  • 通过 javascript 添加 HTML 控件

    有些东西让我困惑 这似乎是显而易见的 但我不太明白 当用户更改下拉列表的值时 我想向页面 普通旧 html 添加 删除几个 HTML 控件 一个示例是为请求的每个 多个 房间添加或删除 此房间的客人数量 文本框 因此 如果用户选择 1个房间
  • 如何在表单中创建 html 元素而不重新加载页面?

    我正在寻找一种通过使用按钮等方式将 html 元素添加到表单中的方法 我一直在寻找一些例子 但它们非常大 比如我想要构建的实际表单大小的 3 倍以上 所以我想知道是否有更好的方法来解决这个问题 我的想法是这样的
  • 好的 JQuery 散点图插件(包括示例图片)?

    我正在寻找一个可靠的 JQuery 图形插件 它可以为我的网站提供有吸引力的散点图 我真的不需要很多花哨的功能 只需要根据我给出的 X 轴和 Y 轴值在图表上绘制点的能力 我唯一有点特殊的要求是这些点能够呈现不同的颜色 除了跟踪 X 轴上的
  • 什么是“你好,世界!” “std::ref”的例子?

    有人可以举一个简单的例子来演示功能std ref 我的意思是使用一些其他构造 如元组或数据类型模板 的示例only if无法解释std ref没有他们 我发现了两个问题std ref here https stackoverflow com
  • 如何编辑 UIAlertAction 文本字体大小和颜色

    如何编辑UIAlertAction文字大小和颜色 我已经采取了UIAlertController根据它如何编辑尺寸 这是我的代码 UIAlertController controller UIAlertController alertCon
  • Ruby 捆绑程序身份验证错误

    我从捆绑器中收到了一个我以前从未见过的奇怪错误 在bundle install I get Please CGI escape your usernames and passwords before setting them for aut
  • 如何使 Mercurial (hgwebdir) rss/atom 提要显示分支名称

    我想配置我们的 Mercurial 服务器安装 以便 rss atom 提要除了标准字段 标题 guid 描述 作者 pubDate 之外 还将发布变更集的分支名称 安装位置不同 但在 ubuntu 上您会找到相关文件 usr share
  • 将鼠标悬停在元素上时使用 jQuery 更改标题属性

    我有一个 div 按钮 它有一个 title 属性 我们将其用作使用 jQueryUI 的工具提示文本 我想通过单击来更改按钮的工具提示 但是 当单击按钮并触发回调函数时 鼠标位于 div 上且标题为空 我该如何解决这个问题 看起来 jQu
  • SequelizeConnectionError:自签名证书

    我正在尝试连接到我在 Heroku 中设置的 PostgreSQL 数据库 const Sequelize DataTypes Model require sequelize DB Configuration const sequelize
  • g++ 无法在 Windows 命令提示符下运行。已安装 Cygwin

    我已经安装了 Eclipse 和 CDT 在 Eclipse 中使用 C C 需要 CDT 并安装了 Cygwin 以便我可以编译我的文件 在环境变量中 我将路径设置为包含以下内容 C cygwin bin g make 和 GDC 都是通
  • node.exe 文件是做什么用的?

    我在学Node js在 Windows 环境下 到目前为止 我一直在使用Node js command prompt运行命令的快捷方式 但 Windows 安装程序还会创建一个快捷方式 名为Node js指向 C Program Files
  • 如何设置全局容器(C++03)?

    我想定义一个全局容器 C 03 这是我尝试过的示例代码 但它不起作用 include
  • 使用电子邮件作为用户名有哪些优点和缺点? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 为什么矢量化 numpy 代码比 for 循环慢?

    我有两个 numpy 数组 X and Y 有形状 n d and m d 分别 假设我们要计算每行之间的欧几里得距离X和每一行Y并将结果存储在数组中Z有形状 n m 我对此有两个实现 第一个实现使用两个 for 循环 如下所示 for i