Julia 中的内存分配

2024-03-24

将程序从 Python 翻译成 Julia 后,我非常不满意:

  • 对于小/非常小的输入,Python 更快
  • 对于中等输入,Julia 更快(但没那么快)
  • 对于大输入,Python 更快

我认为原因是我不明白内存分配是如何工作的(这里自学者,没有CS背景)。我会在这里发布我的代码,但它太长且太具体,除了我之外,它对任何人都没有好处。因此我做了一些实验,现在我有一些问题。

考虑这个简单的script.jl:

function main()
    @time begin
        a = [1,2,3]
    end
end
main()

当我运行它时,我得到:

$ julia script.jl
  0.000004 seconds (1 allocation: 96 bytes)

1.为什么是 96 字节?当我设置a = []我得到 64 个字节(为什么空数组的重量如此之大?)。 96 字节 - 64 字节 = 32 字节。但a is an Array{Int64,1}。 3 * 64 位 = 3 * 8 字节 = 24 字节!= 32 字节。

2.为什么我设置了还是得到96字节a = [1,2,3,4]?

3.为什么我运行此命令时会得到 937.500 KB:

function main()
    @time begin
        for _ in 1:10000
            a = [1,2,3]
        end
    end
end
main()

而不是 960.000 KB?

4.为什么,例如,filter()这么低效?看看这个:

check(n::Int64) = n % 2 == 0

function main()
    @time begin
        for _ in 1:1000
            a = [1,2,3]
            b = []
            for x in a
                check(x) && push!(b,x)
            end
            a = b
        end
    end
end
main()
$ julia script.jl
  0.000177 seconds (3.00 k allocations: 203.125 KB)

instead:

check(n::Int64) = n % 2 == 0

function main()
    @time begin
        for _ in 1:1000
            a = [1,2,3]
            a = filter(check,a)
        end
    end
end
main()

$ julia script.jl
  0.002029 seconds (3.43 k allocations: 225.339 KB)

如果我使用匿名函数(x -> x % 2 == 0)我得到的不是检查内部过滤器,而是:

$ julia script.jl
  0.004057 seconds (3.05 k allocations: 206.555 KB)

如果内置函数速度较慢并且需要更多内存,为什么我应该使用它?


快速解答:

1. Array除其他外,我们还可以在标题中跟踪它们的维度和大小。

2. Julia 确保其数组是16 字节对齐 https://en.wikipedia.org/wiki/Data_structure_alignment。如果您查看更多示例的分配情况,该模式就会变得显而易见:

julia> [@allocated(Array{Int64}(i)) for i=0:8]'
1x9 Array{Any,2}:
 64  80  80  96  96  112  112  128  128

3. 以千字节为单位进行报告。 1 KB 有 1024 个字节:

julia> 937.500 * 1024
960000.0

4. 匿名函数和将函数传递给高阶函数,例如filter是 0.4 中已知的性能问题,并已在最新的开发版本中修复。

一般来说,获得比预期更多的分配通常是类型不稳定的标志。我强烈建议阅读手册性能提示页面 http://docs.julialang.org/en/release-0.4/manual/performance-tips/有关此的更多信息。

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

Julia 中的内存分配 的相关文章

  • 每当调用 malloc/free 时输出到 stderr

    使用 Linux GCC C 每当调用 malloc free new delete 时 我想向 stderr 记录一些内容 我试图了解库的内存分配 因此我想在运行单元测试时生成此输出 我使用 valgrind 进行内存泄漏检测 但我找不到
  • DbConnection 不带 Db,使用内存中的 DataSet(或类似的)作为源

    我正在尝试对一些 NET 类进行单元测试 这些类 出于良好的设计原因 需要 DbConnections 来完成其工作 对于这些测试 我在内存中有某些数据可以作为这些类的输入 内存中的数据可以很容易地表示为 DataTable 或包含该 Da
  • 估算缺失数据,同时强制相关系数保持不变

    考虑以下 excel 数据集 m r 2 0 3 3 0 8 4 0 1 3 2 1 5 2 2 3 1 9 2 5 1 2 3 0 2 0 2 6 我的目标是使用以下条件填充缺失值 将上述两列之间的成对相关性表示为 R 大约 0 68 将
  • 有关 Linux 内存类型的问题

    关于Linux内存我有以下问题 我知道活动内存是最常访问的内存部分 但是有人可以解释一下 linux 如何考虑将内存位置用于活动内存或非活动内存 主动存储器由哪些部分组成 磁盘 文件缓存是否被视为活动内存的一部分 有什么区别Buffers
  • WPF 窗口关闭后不会释放内存

    我创建了一个测试代码 private void Application Startup 1 object sender StartupEventArgs e ShutdownMode System Windows ShutdownMode
  • List.Clear() 在 C# 中是如何实现的?

    我假设它使用数组来实现 List 怎么List Clear 实施的 它实际上清理了数组还是只是为此列表创建了一个新数组 public class List private Array array public void Clear1 arr
  • 从 QML 实例化 C++ 对象会产生巨大的内存使用开销

    实例化一个QObjectC 堆中的派生类为每个对象提供了大约 160 个字节 通过注册相同的对象qmlRegisterType 用于从 QML 创建并通过以下方式动态创建对象createObject 每个对象给我 2000 多个字节 这是完
  • gcc 不太可能使用宏

    我正在编写一段关键代码 其逻辑大致如下 if expression is true do something with extremely low latency before the nuke blows up This branch i
  • 为什么如果内存组织为字,则程序计数器加 1;如果内存组织为字节,则程序计数器加 2?

    如果在计算机中一条指令是 16 位 并且如果存储器被组织为 16 位字 则通过在当前指令的地址中加 1 来计算下一条指令的地址 如果内存是按字节组织的 可以单独寻址 那么我们需要在当前指令地址上加二 得到顺序执行的下一条指令的地址 为什么会
  • OpenCL 何时使用全局、私有、本地、常量地址空间

    我正在尝试学习 OpenCL 但我很难决定使用哪些地址空间 因为我只找到组装的资源声明这些地址空间是什么 但没有声明它们为什么存在或何时使用它们 资源至少太分散了 所以带着这个问题我希望把所有这些信息汇总一下 所有地址空间是什么 它们为什么
  • 为什么结构中“[0]byte”的位置很重要?

    0 byte在golang中不应该占用任何内存空间 但这两个结构体的大小不同 type bar2 struct A int 0 byte type bar3 struct 0 byte A int 那么为什么这个位置 0 byte这里重要吗
  • Java:为什么它使用固定数量的内存?或者它如何管理内存?

    JVM 似乎使用了一些固定数量的内存 至少我经常看到参数 Xmx 对于最大尺寸 和 Xms 对于初始大小 这表明 我感觉 Java 应用程序不能很好地处理内存 我注意到一些事情 即使一些非常小的示例演示应用程序也会加载大量内存 也许这是因为
  • 64 位大型 malloc

    malloc 失败的原因是什么 尤其是在 64 位中 我的具体问题是尝试在 64 位系统上分配一大块 10GB RAM 该机器有 12GB RAM 和 32GB 交换空间 是的 malloc 是极端的 但是为什么它会成为一个问题呢 这是在带
  • 如何在 Julia 中进行两个变量数值积分?

    我可以使用 Julia 在 Julia 中进行单变量数值积分quadgk 一些简单的例子 julia gt f x cos x f generic function with 1 method julia gt quadgk f 0 pi
  • 应用程序无缘无故地被杀死。怀疑 BSS 高。如何调试呢?

    我已经在CentOs6 6中成功运行我的应用程序 最近 硬件 主板和内存 更新了 我的应用程序现在毫无理由地被杀死 root localhost PktBlaster PktBlaster Killed 文件和 ldd 输出 root lo
  • c# 通过内存地址调用方法

    我正在尝试在 C 中的指定内存地址调用函数 以下是我在 C 中的操作方法 typedef void do int i auto doActor do 0xAAAABEEF doActor 1 如果可能的话 如何在 C 中复制这种行为 对 C
  • 赋值运算符和复制构造函数有什么区别?

    我不明白C 中赋值构造函数和复制构造函数之间的区别 是这样的 class A public A cout lt lt A A lt lt endl The copy constructor A a b The assignment cons
  • 在 C 中复制两个相邻字节的最快方法是什么?

    好吧 让我们从最明显的解决方案开始 memcpy Ptr const char a b 2 调用库函数的开销相当大 编译器有时不会优化它 我不会依赖编译器优化 但即使 GCC 很聪明 如果我将程序移植到带有垃圾编译器的更奇特的平台上 我也不
  • 如何使用GDB修改内存内容?

    我知道我们可以使用几个命令来访问和读取内存 例如 print p x 但是如何更改任何特定位置的内存内容 在 GDB 中调试时 最简单的是设置程序变量 参见GDB 分配 http sourceware org gdb current onl
  • “gld/st_throughput”和“dram_read/write_throughput”指标之间有什么区别?

    在 CUDA 可视化分析器版本 5 中 我知道 gld st requested throughput 是应用程序请求的内存吞吐量 然而 当我试图找到硬件的实际吞吐量时 我很困惑 因为有两对似乎合格的指标 它们是 gld st throug

随机推荐