我不太了解矢量化,但我有兴趣了解为什么像 python 这样的语言不能通过库接口(interface)对可迭代对象提供矢量化,就像它提供线程支持一样。我知道许多 numpy 方法都是矢量化的,但必须使用 numpy 进行通用计算可能会受到限制。
我目前的理解是 python 无法向量化函数,即使它们匹配“SIMD”模式。例如,理论上任何列表理解或 map()
函数的使用都不应该是可向量化的,因为它们输出的列表是对输入列表中的独立输入运行相同函数的结果?
以我幼稚的理解,似乎任何时候我使用map()
,理论上,我都应该能够创建一个表示函数的指令集;然后输入中的每个元素只需要通过编译的相同函数运行。设计提供 simd_map(func, iterable)
的工具的技术挑战是什么,它试图“及时”编译 func
,然后从 iterable
并利用处理器的 simd 功能通过 func()
?
谢谢!
最佳答案
map
应用的操作是任意 Python 代码。 CPython 是解释器,而不是 JIT 编译器。
CPython 可以 可能有一些固定的 C 函数(作为解释器的一部分提前编译)用于对数组进行 SIMD 操作,但它没有 AFAIK。即便如此,它也必须将提供的 func
优化为它可以进行模式识别的东西,以注意到它是,例如执行 a[i] = max(a[i], some_value)
。
但通常 CPython 不会那样做;解释器开销是遍历数组元素的一个巨大问题。 CPython 远不及 原生标量循环的性能,因此即使没有自动矢量化,也有很大的提升空间。 就像 IIRC 慢 200 倍。例如Why are bitwise operators slower than multiplication/division/modulo?表明某些操作甚至没有用于小整数的“快速路径”,并且该开销足以使 &
比内部使用硬件的 //
慢划分指令。
此外,Python 列表不会存储为 int32_t
或 double
的简单连续数组,因此 CPU SIMD 无论如何都不高效。这就是 numpy 数组的特殊之处:它们存储值的方式类似于原始类型的 C 数组。
(警告:我几乎不了解 Python,也不经常使用它。但我认为我知道的足以让这个答案是正确的:它是一个用 C 语言编写的解释器,不会即时生成 native 机器代码。唯一可以运行的 native 循环是作为解释器的一部分或在 NumPy 库中预编译的循环。)
关于python - 为什么 python 不能矢量化 map() 或列表理解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58035479/