You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

macOS中Swift Decimal性能为何比Python Decimal慢2.5倍?

Swift Decimal vs Python Decimal 性能差异排查与优化建议

测试环境与结果

环境配置

  • macOS Sonoma 14.5
  • Xcode 15.4
  • Apple M3 Max芯片
  • Python 3.12

测试结果

  • Double类型运算:Python完成50亿次计算耗时241秒;Swift仅需1.3秒,性能提升约191倍。
  • Decimal高精度运算:Python完成2亿次计算耗时73秒;Swift需186秒,且尾数精度更低,性能慢约2.6倍。

更新说明

已在Swift中使用GMP库运行相同测试,速度比Swift Decimal快约10倍(为当前场景下的性能上限),但仍困惑为何Python Decimal比Swift Decimal快2.5倍。

已在Release模式下编译Swift代码,寻求问题排查建议或高效高精度数学库推荐。


测试代码

Python代码

import random
import time
import math
from time import process_time, time
from decimal import *

REPEAT_CALC = 10000
INPUTS_COUNT = 20000

inputs = []
calculations = 0
functions = 0

for i in range(0, INPUTS_COUNT):
    input = (Decimal(random.randint(1, 10)), Decimal(random.randint(1, 10)))
    inputs.append(input)

def calculate(x, y):
    global calculations
    global functions
    Decimal_pi = Decimal(math.pi)
    functions += 1
    hypo = Decimal(0)
    for i in range(0, REPEAT_CALC):
        hypo = (x / Decimal_pi) * (y / Decimal_pi)
        calculations += 1
    return hypo

def get_calculations(inputs):
    solutions = []
    for input in inputs:
        solutions.append(calculate(input[0], input[1]))
    return solutions

time_started = time()
ptime_started = process_time()
solutions = get_calculations(inputs)
ptime_ended = process_time()
time_ended =  time()

print("functions:", functions, "calculations:", calculations, "duration:", (time_ended - time_started)*1000, "ms cputime:", (ptime_ended - ptime_started) * 1000.0, "ms pi:", Decimal(math.pi))

Swift代码

import Foundation
import Cocoa

let REPEAT_CALC: Int = 10000
let INPUTS_COUNT: Int = 20000

let clock = ContinuousClock()

var inputs: [(Decimal, Decimal)] = [(Decimal, Decimal)]()
inputs.reserveCapacity(INPUTS_COUNT)
var calculations: Int = 0
var functions: Int = 0

for _ in 0 ..< INPUTS_COUNT
{
    inputs.append((Decimal(Int.random(in: 1..<10)), Decimal(Int.random(in: 1..<10))))
}

func calculate(x: Decimal, y: Decimal) -> Decimal
{
    functions += 1
    var hypo: Decimal = 0
    for _ in 0 ..< REPEAT_CALC
    {
        hypo = (x/Decimal.pi) * (y/Decimal.pi)
        calculations += 1
    }
    return hypo
}

func get_calculations(my inputs: [(Decimal, Decimal)]) -> [Decimal]
{
    var solutions: [Decimal] = []
    solutions.reserveCapacity(inputs.count)
    for input in inputs
    {
        solutions.append(calculate(x: input.0, y: input.1))
    }
    return solutions
}

var solutions: [Decimal] = []
let time = clock.measure
{
    solutions = get_calculations(my: inputs)
}
print("functions: \(functions) calculations: \(calculations) duration: \(Double(time.components.seconds) * 1000 + Double(time.components.attoseconds) * 1e-15)ms pi:", Decimal.pi)

排查建议

  1. 缓存常量减少重复计算:Swift代码中每次循环都访问Decimal.pi,可将其提前缓存为常量,避免重复初始化开销:
    let pi = Decimal.pi
    func calculate(x: Decimal, y: Decimal) -> Decimal {
        // 后续用pi替代Decimal.pi
    }
    
  2. 简化运算逻辑:将(x/pi) * (y/pi)优化为x * y / (pi * pi),或者预计算1/(pi*pi)的倒数,减少除法操作(除法运算远慢于乘法):
    let invPiSquared = Decimal(1) / (pi * pi)
    // 循环内改为:hypo = x * y * invPiSquared
    
  3. 检查编译优化选项:确认Release模式下已开启最高优化级别-O,并针对Apple Silicon架构启用特定优化(如-target arm64-apple-macos14),关闭调试符号与断言。
  4. 减少全局变量开销:全局变量calculations和functions的读写会带来原子操作开销,可改为局部变量并通过闭包返回统计值,或者使用UnsafeMutablePointer直接操作内存。
  5. 循环优化:使用Swift的map替代手动for循环,让编译器进行自动循环展开与向量化优化;或者将循环逻辑内联到主函数,减少函数调用开销。

高效高精度数学库推荐

  • GMP:已验证比Swift Decimal快10倍,是当前场景下的性能上限选择,需通过C桥接在Swift中集成,支持任意精度的整数与浮点数运算。
  • DecimalSwift:第三方Swift Decimal实现,针对Swift生态优化,性能优于Foundation的NSDecimal,API更贴合Swift语法。
  • Swift Numerics:苹果官方数值计算库,提供高性能的浮点数运算组件,可结合高精度库使用以优化特定场景。
  • BigInt:专注于大整数运算的高性能库,若业务场景以整数运算为主,可优先选择。

内容的提问来源于stack exchange,提问作者nilgirian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 02:59:51