Julia 学习笔记——性能优化与并行计算
Some content in this article was created with AI assistance. Please verify as needed.Julia 最大的吸引力之一,就是“高层写法”和“高性能”之间的距离没有传统动态语言那么远。 但这并不意味着随便写都能快。Julia 的性能优化有一套非常典型的思路,而并行计算又是另一个常被误解的话题,所以这里把它们放到一篇里做一个够用版整理。 概述先记下面几点: Julia 可以快,但前提是写法利于类型推断和特化编译; 第一次运行慢,往往是编译开销,不一定是算法本身慢; 真正的性能问题,很多时候不是“语法不够底层”,而是分配太多、类型不稳定、全局变量太多; 并行计算不是给代码加个宏就自动变快,任务划分、内存分配和数据传递同样重要。 性能分析基础@time最基本的计时方式: 1@time sum(rand(10^6)) 它一般会显示: 执行时间; 内存分配次数与大小; GC 时间比例等。 但是要特别注意:第一次运行时通常包含编译成本,所以参考意义有限。 更稳妥的做法是至少跑两次: 12@time f(x...
Julia 学习笔记——线性代数
Some content in this article was created with AI assistance. Please verify as needed.数组是 Julia 的核心内容之一,而线性代数则是它真正发力的主场。虽然前面的数组笔记已经涉及了一些矩阵和广播,但如果不单独整理一篇,很多线性代数语义还是容易和“普通数组运算”混在一起。 概述Julia 的线性代数体验和 Python/Numpy、MATLAB 既相似又不同: 和 MATLAB 一样,矩阵乘法直接使用 *; 和 Python/Numpy 一样,元素访问写成 A[i, j]; 但 Julia 的标准库 LinearAlgebra 还引入了很多特殊矩阵类型和分解对象,它们不是简单的“二维数组”。 因此看 Julia 里的线性代数代码时,需要同时区分: 这是普通数组操作; 还是线性代数意义上的操作; 结果是立即物化的数组,还是带语义的特殊对象。 LinearAlgebra 标准库线性代数相关功能主要来自标准库: 1using LinearAlgebra 它不是默认自动导入的...
Julia 学习笔记——补充. 与 Python 和 MATLAB 的差异整理
Some content in this article was created with AI assistance. Please verify as needed.这一篇把 Julia 与 Python、MATLAB 的主要差异集中整理一下,方便在系统看各个专题之前先有个整体印象。 先说明几点: 下文默认读者已经熟悉 Python 和 MATLAB; 默认以 Julia 1.12 系列为准; 这里只做迁移视角下的差异整理,不追求把所有细节一次性讲完; 真正的语法和行为细节,仍然以后面各专题笔记为主。 概述如果只用一句话概括,Julia 大致可以理解为: 语法观感上吸收了 Python、MATLAB、Fortran 等科学计算语言的很多习惯; 执行模型上又明显更接近带 JIT 的编译型语言; 语言设计中心不是 class,而是数组、数值计算、泛型函数和多重分派。 因此,从 Python 或 MATLAB 迁移到 Julia 时,真正需要适应的往往不是“语法会不会写”,而是下面这些更底层的习惯: 语言默认鼓励什么样的代码组织方式; 哪些直觉来自 Python,哪些来自...
Julia 学习笔记——10. 输入输出与文件交互
Some content in this article was created with AI assistance. Please verify as needed.前面的基础笔记里已经零散提到过 print、println、readline 这些最简单的输入输出操作,但如果要真正写脚本或小工具,还需要文件读写和路径处理。 概述Julia 中与 IO 相关的几类操作包括: 控制台输入输出; 文本文件和二进制文件; open do 风格的资源管理; 常见的路径、目录和文件系统操作。 整体上,Julia 的 IO 风格更接近“显式流对象 + open do 管理资源”,而不是 MATLAB 那种偏工作区工具式接口。 控制台输入输出print 和 println最常用的输出函数仍然是: 12print("hello")println("world") 区别很简单: print 不自动换行; println 自动在末尾补一个换行。 也可以连续输出多个对象: 1println("x = ", 1, ", y...
Julia 学习笔记——9. 宏与元编程
Some content in this article was created with AI assistance. Please verify as needed.宏和元编程是 Julia 里非常有代表性的部分。它们既是语言能力的一部分,也是很多 Julia 代码看起来“很不一样”的原因。 不过宏虽然重要,但绝对不是日常写 Julia 代码的起点。大多数普通逻辑都应该优先写成函数,只有当函数做不到,或者语法层面介入明显更自然时,才值得考虑宏。 概述Julia 的宏并不是 C 语言那种简单文本替换,而是基于语法树(AST)的代码变换工具。 可以先这样理解: 函数操作的是“值”; 宏操作的是“代码表达式”; 宏在代码真正运行前先展开; 展开结果再交给 Julia 去编译和执行。 因此,宏更像是“改写代码的工具”,而不是普通的可调用逻辑。 宏的基本形式最简单的宏定义如下: 123macro sayhello() return :(println("Hello, World!"))end 调用时使用 @: 1@sayhello 输出: 1Hello...
Julia 学习笔记——8. 模块与包
Some content in this article was created with AI assistance. Please verify as needed.前面的几篇基本还是语言语法层面的内容,这一篇开始看 Julia 代码组织和包管理。 需要先说明一下:Julia 的模块系统、项目环境、包管理其实是三个相关但不完全相同的话题: 模块(module):解决名字空间和代码组织问题; 项目环境(environment):解决当前项目依赖哪些包的问题; 包(package):解决代码如何发布、复用、安装的问题。 这几部分在 Julia 里结合得比较紧,但概念上最好还是分开理解。 概述默认读者已经熟悉 Python 和 MATLAB,这里就不再从“什么是模块”这种层面展开,直接讨论 Julia 的实际组织方式。 如果只写单文件脚本,那么模块和包的存在感不会太强;但只要代码规模稍微大一点,就必须开始区分: 哪些东西属于当前模块自己的名字空间; 哪些代码只是拆文件,应该用 include; 哪些依赖来自外部包,应该交给项目环境和 Pkg 管理。 模块基础为什么需要模块如...
Julia 学习笔记——7. 多维数组
Some content in this article was created with AI assistance. Please verify as needed.数组是 Julia 最核心的主题之一。前面几篇虽然已经零散提过一些数组相关语法,但如果不专门单独整理一篇,很多地方还是会比较乱。 这一篇主要记录: Julia 的数组字面量和创建方式; 索引、切片、视图、形状变换; 常见的数组运算、拼接、遍历和广播; Julia 数组系统里最值得重点记住的设计点。 概述Julia 的 Array 是按列优先(column-major)存储的,这一点和 MATLAB、Fortran 一致,和 Numpy 默认的行优先风格不同。 默认读者已经熟悉 Python/Numpy 或 MATLAB,因此这里不再解释数组的基础概念,直接看 Julia 数组系统里最容易影响实际写法的部分:一维向量和二维矩阵的区分、闭区间切片、默认拷贝而不是默认视图、广播和点语法。 此外 Julia 的数组有几个很鲜明的特点: 真正区分一维向量 Vector 和二维矩阵 Matrix; 索引从 1...
Julia 学习笔记——6. 函数进阶
Some content in this article was created with AI assistance. Please verify as needed.前面的函数笔记主要记录函数的基本语法,这一篇继续看 Julia 函数体系里更核心的部分:方法、多重分派、参数化方法、构造函数,以及一些常用的函数式写法。 概述如果说前一篇还只是“怎么把函数写出来”,那么这一篇才真正开始接触 Julia 函数系统最有代表性的部分。 在 Python 中,函数更多只是可调用对象;而在 Julia 中,函数名背后通常对应的是一整组方法实现,调用时再根据参数类型决定走哪一个。 默认读者已经熟悉 Python / MATLAB,因此这里也不再解释高阶函数、匿名函数这些概念本身,直接看 Julia 的实现方式。 函数的参数类型Julia 允许给函数的(一部分或全部)参数加上类型约束,例如 123function add2(x::Int64, y::Int64) return x + yend 正常使用例如 12add2(1, 3) # 4add2(Int64(1), Int...
Julia 学习笔记——5. 变量作用域与类型系统
Some content in this article was created with AI assistance. Please verify as needed.Julia 的作用域和类型系统的设计非常规范化。相对于 Python 或 MATLAB,Julia 在这两部分会明显显得更“讲规矩”。 这一篇主要关注两个问题: 变量名在什么地方可见,什么时候会新建局部变量; Julia 的类型系统到底是怎样组织的,平时写代码应该关注到什么程度。 如果只从“写脚本”的角度看,Julia 和 Python 确实有很多相似之处;但一旦开始关心性能、分派和泛型代码,Julia 的作用域和类型系统就会立刻变成核心内容。 变量作用域基本概念Julia 使用词法作用域(lexical scope),也就是一个变量在函数内部能否被访问,取决于函数定义的位置,而不是调用的位置。 例如 1234567x = 10function f() return xendf() # 10 这里 f() 可以访问到外部定义的 x,是因为 x 在 f 定义处可见。 需要注意,Julia 中并不是所有语...
Julia 学习笔记——4. 函数基础
Some content in this article was created with AI assistance. Please verify as needed.Julia 中的函数在表面上和 Python 比较接近,都是语言的一等公民:可以赋值给变量、作为参数传递,也可以作为返回值返回。 不过 Julia 的函数体系又远不只是把 def 换成 function 这么简单,语法会比 Python 严格得多。函数返回值、默认参数、关键字参数、元组参数,以及后面会单独展开的多重分派,都是这个语言里非常核心的内容。 函数格式Julia 中最普通的函数定义格式如下: 1234function function_name(parameter_list) function_body return resultend 其中: function 和 end 用来包裹函数定义; 参数列表写在小括号中; 返回值可以显式使用 return,也可以依赖最后一个表达式自动返回。 对于非常简单的函数,也可以使用单行赋值形式,后面会单独讨论。 简单示例简单例子最基本的例子如下 123...
