|
| 1 | +#!/usr/bin/env python |
| 2 | +import os |
| 3 | +from time import clock |
| 4 | +import numpy as np |
| 5 | +import sympy as sp |
| 6 | +from sympy.parsing.sympy_parser import parse_expr |
| 7 | +from sympy.parsing.sympy_parser import standard_transformations |
| 8 | +import symengine as se |
| 9 | +import warnings |
| 10 | + |
| 11 | +exprs_s = open(os.path.join(os.path.dirname(__file__), '6_links_rhs.txt'), 'tr').read() |
| 12 | +exprs = parse_expr(exprs_s, transformations=standard_transformations) |
| 13 | +args = sp.Matrix(1, 14, exprs).free_symbols |
| 14 | +inp = np.ones(len(args)) |
| 15 | +assert inp.size == 26 |
| 16 | +print([expr.subs(dict(zip(args, [1]*len(args)))) for expr in exprs]) |
| 17 | + |
| 18 | +# Real-life example (ion speciation problem in water chemistry) |
| 19 | + |
| 20 | + |
| 21 | +lmb_sp = sp.lambdify(args, exprs, modules='math') |
| 22 | +lmb_se = se.Lambdify(args, exprs) |
| 23 | +# lmb_se_cse = se.LambdifyCSE(args, exprs) |
| 24 | +lmb_se_llvm = se.Lambdify(args, exprs, backend='llvm') |
| 25 | + |
| 26 | + |
| 27 | +lmb_sp(*inp) |
| 28 | +tim_sympy = clock() |
| 29 | +for i in range(500): |
| 30 | + res_sympy = lmb_sp(*inp) |
| 31 | +tim_sympy = clock() - tim_sympy |
| 32 | + |
| 33 | +lmb_se(inp) |
| 34 | +tim_se = clock() |
| 35 | +res_se = np.empty(len(exprs)) |
| 36 | +for i in range(500): |
| 37 | + res_se = lmb_se(inp) |
| 38 | +tim_se = clock() - tim_se |
| 39 | + |
| 40 | +# lmb_se_cse(inp) |
| 41 | +# tim_se_cse = clock() |
| 42 | +# res_se_cse = np.empty(len(exprs)) |
| 43 | +# for i in range(500): |
| 44 | +# res_se_cse = lmb_se_cse(inp) |
| 45 | +# tim_se_cse = clock() - tim_se_cse |
| 46 | + |
| 47 | +lmb_se_llvm(inp) |
| 48 | +tim_se_llvm = clock() |
| 49 | +res_se_llvm = np.empty(len(exprs)) |
| 50 | +for i in range(500): |
| 51 | + res_se_llvm = lmb_se_llvm(inp) |
| 52 | +tim_se_llvm = clock() - tim_se_llvm |
| 53 | + |
| 54 | + |
| 55 | +print('SymEngine (lambda double) speed-up factor (higher is better) vs sympy: %12.5g' % |
| 56 | + (tim_sympy/tim_se)) |
| 57 | + |
| 58 | +# print('symengine (lambda double + CSE) speed-up factor (higher is better) vs sympy: %12.5g' % |
| 59 | +# (tim_sympy/tim_se_cse)) |
| 60 | + |
| 61 | +print('symengine (LLVM) speed-up factor (higher is better) vs sympy: %12.5g' % |
| 62 | + (tim_sympy/tim_se_llvm)) |
| 63 | + |
| 64 | +import itertools |
| 65 | +from functools import reduce |
| 66 | +from operator import mul |
| 67 | + |
| 68 | +def ManualLLVM(inputs, *outputs): |
| 69 | + outputs_ravel = list(itertools.chain(*outputs)) |
| 70 | + cb = se.Lambdify(inputs, outputs_ravel, backend="llvm") |
| 71 | + def func(*args): |
| 72 | + result = [] |
| 73 | + n = np.empty(len(outputs_ravel)) |
| 74 | + t = cb.unsafe_real(np.concatenate([arg.ravel() for arg in args]), n) |
| 75 | + start = 0 |
| 76 | + for output in outputs: |
| 77 | + elems = reduce(mul, output.shape) |
| 78 | + result.append(n[start:start+elems].reshape(output.shape)) |
| 79 | + start += elems |
| 80 | + return result |
| 81 | + return func |
| 82 | + |
| 83 | +lmb_se_llvm_manual = ManualLLVM(args, np.array(exprs)) |
| 84 | +lmb_se_llvm_manual(inp) |
| 85 | +tim_se_llvm_manual = clock() |
| 86 | +res_se_llvm_manual = np.empty(len(exprs)) |
| 87 | +for i in range(500): |
| 88 | + res_se_llvm_manual = lmb_se_llvm_manual(inp) |
| 89 | +tim_se_llvm_manual = clock() - tim_se_llvm_manual |
| 90 | +print('symengine (ManualLLVM) speed-up factor (higher is better) vs sympy: %12.5g' % |
| 91 | + (tim_sympy/tim_se_llvm_manual)) |
| 92 | + |
| 93 | +if tim_se_llvm_manual < tim_se_llvm: |
| 94 | + warnings.warn("Cython code for Lambdify.__call__ is slow.") |
| 95 | + |
| 96 | +import setuptools |
| 97 | +import pyximport |
| 98 | +pyximport.install() |
| 99 | +from Lambdify_6_links_reference import _benchmark_reference_for_Lambdify as lmb_ref |
| 100 | + |
| 101 | +lmb_ref(inp) |
| 102 | +tim_ref = clock() |
| 103 | +for i in range(500): |
| 104 | + res_ref = lmb_ref(inp) |
| 105 | +tim_ref = clock() - tim_ref |
| 106 | +print('Hard-coded Cython code speed-up factor (higher is better) vs sympy: %12.5g' % |
| 107 | + (tim_sympy/tim_ref)) |
0 commit comments