|
| 1 | +#!/usr/bin/env python |
1 | 2 | from time import clock
|
2 | 3 | import numpy as np
|
3 | 4 | import sympy as sp
|
4 | 5 | import symengine as se
|
| 6 | +import warnings |
5 | 7 |
|
6 | 8 | # Real-life example (ion speciation problem in water chemistry)
|
7 | 9 |
|
|
10 | 12 | args = np.concatenate((x, p))
|
11 | 13 | exp = sp.exp
|
12 | 14 | exprs = [x[0] + x[1] - x[4] + 36.252574322669, x[0] - x[2] + x[3] + 21.3219379611249, x[3] + x[5] - x[6] + 9.9011158998744, 2*x[3] + x[5] - x[7] + 18.190422234653, 3*x[3] + x[5] - x[8] + 24.8679190043357, 4*x[3] + x[5] - x[9] + 29.9336062089226, -x[10] + 5*x[3] + x[5] + 28.5520551531262, 2*x[0] + x[11] - 2*x[4] - 2*x[5] + 32.4401680272417, 3*x[1] - x[12] + x[5] + 34.9992934135095, 4*x[1] - x[13] + x[5] + 37.0716199972041, p[0] - p[1] + 2*p[10] + 2*p[11] - p[12] - 2*p[13] + p[2] + 2*p[5] + 2*p[6] + 2*p[7] + 2*p[8] + 2*p[9] - exp(x[0]) + exp(x[1]) - 2*exp(x[10]) - 2*exp(x[11]) + exp(x[12]) + 2*exp(x[13]) - exp(x[2]) - 2*exp(x[5]) - 2*exp(x[6]) - 2*exp(x[7]) - 2*exp(x[8]) - 2*exp(x[9]), -p[0] - p[1] - 15*p[10] - 2*p[11] - 3*p[12] - 4*p[13] - 4*p[2] - 3*p[3] - 2*p[4] - 3*p[6] - 6*p[7] - 9*p[8] - 12*p[9] + exp(x[0]) + exp(x[1]) + 15*exp(x[10]) + 2*exp(x[11]) + 3*exp(x[12]) + 4*exp(x[13]) + 4*exp(x[2]) + 3*exp(x[3]) + 2*exp(x[4]) + 3*exp(x[6]) + 6*exp(x[7]) + 9*exp(x[8]) + 12*exp(x[9]), -5*p[10] - p[2] - p[3] - p[6] - 2*p[7] - 3*p[8] - 4*p[9] + 5*exp(x[10]) + exp(x[2]) + exp(x[3]) + exp(x[6]) + 2*exp(x[7]) + 3*exp(x[8]) + 4*exp(x[9]), -p[1] - 2*p[11] - 3*p[12] - 4*p[13] - p[4] + exp(x[1]) + 2*exp(x[11]) + 3*exp(x[12]) + 4*exp(x[13]) + exp(x[4]), -p[10] - 2*p[11] - p[12] - p[13] - p[5] - p[6] - p[7] - p[8] - p[9] + exp(x[10]) + 2*exp(x[11]) + exp(x[12]) + exp(x[13]) + exp(x[5]) + exp(x[6]) + exp(x[7]) + exp(x[8]) + exp(x[9])]
|
13 |
| -lmb_symengine = se.Lambdify(args, exprs) |
14 |
| -lmb_sympy = sp.lambdify(args, exprs) |
| 15 | +lmb_sp = sp.lambdify(args, exprs) |
| 16 | +lbm_se = se.Lambdify(args, exprs) |
| 17 | +lbm_se_llvm = se.Lambdify(args, exprs, backend='llvm') |
15 | 18 |
|
16 | 19 | inp = np.ones(28)
|
17 | 20 |
|
18 |
| -tim_symengine = clock() |
19 |
| -res_symengine = np.empty(len(exprs)) |
20 |
| -for i in range(500): |
21 |
| - res_symengine = lmb_symengine(inp) |
22 |
| - #lmb_symengine.unsafe_real_real(inp, res_symengine) |
23 |
| -tim_symengine = clock() - tim_symengine |
24 |
| - |
25 | 21 | tim_sympy = clock()
|
26 | 22 | for i in range(500):
|
27 |
| - res_sympy = lmb_sympy(*inp) |
| 23 | + res_sympy = lmb_sp(*inp) |
28 | 24 | tim_sympy = clock() - tim_sympy
|
29 | 25 |
|
30 |
| -print('symengine speed-up factor (higher is better) vs sympy: %12.5g' % |
31 |
| - (tim_sympy/tim_symengine)) |
| 26 | +tim_se = clock() |
| 27 | +res_se = np.empty(len(exprs)) |
| 28 | +for i in range(500): |
| 29 | + res_se = lbm_se(inp) |
| 30 | +tim_se = clock() - tim_se |
| 31 | + |
| 32 | +tim_se_llvm = clock() |
| 33 | +res_se_llvm = np.empty(len(exprs)) |
| 34 | +for i in range(500): |
| 35 | + res_se_llvm = lbm_se_llvm(inp) |
| 36 | +tim_se_llvm = clock() - tim_se_llvm |
| 37 | + |
| 38 | + |
| 39 | +print('SymEngine (lambda double) speed-up factor (higher is better) vs sympy: %12.5g' % |
| 40 | + (tim_sympy/tim_se)) |
| 41 | + |
| 42 | +print('symengine (LLVM) speed-up factor (higher is better) vs sympy: %12.5g' % |
| 43 | + (tim_sympy/tim_se_llvm)) |
| 44 | + |
| 45 | +import itertools |
| 46 | +from functools import reduce |
| 47 | +from operator import mul |
| 48 | + |
| 49 | +def ManualLLVM(inputs, *outputs): |
| 50 | + outputs_ravel = list(itertools.chain(*outputs)) |
| 51 | + cb = se.Lambdify(inputs, outputs_ravel, backend="llvm") |
| 52 | + def func(*args): |
| 53 | + result = [] |
| 54 | + n = np.empty(len(outputs_ravel)) |
| 55 | + t = cb.unsafe_real(np.concatenate([arg.ravel() for arg in args]), n) |
| 56 | + start = 0 |
| 57 | + for output in outputs: |
| 58 | + elems = reduce(mul, output.shape) |
| 59 | + result.append(n[start:start+elems].reshape(output.shape)) |
| 60 | + start += elems |
| 61 | + return result |
| 62 | + return func |
| 63 | + |
| 64 | +lbm_se_llvm_manual = ManualLLVM(args, np.array(exprs)) |
| 65 | +tim_se_llvm_manual = clock() |
| 66 | +res_se_llvm_manual = np.empty(len(exprs)) |
| 67 | +for i in range(500): |
| 68 | + res_se_llvm_manual = lbm_se_llvm_manual(inp) |
| 69 | +tim_se_llvm_manual = clock() - tim_se_llvm_manual |
| 70 | +print('symengine (ManualLLVM) speed-up factor (higher is better) vs sympy: %12.5g' % |
| 71 | + (tim_sympy/tim_se_llvm_manual)) |
| 72 | + |
| 73 | +if tim_se_llvm_manual < tim_se_llvm: |
| 74 | + warnings.warn("Cython code for Lambdify.__call__ is slow.") |
0 commit comments