Ask Your Question
1

Python kernel seriously slower than SageMath kernel

asked 2021-02-23 23:40:29 +0200

zhaiyu gravatar image

updated 2021-02-24 10:31:41 +0200

Hi, I just found the Python kernel is seriously slower than the SageMath one.

This was the snippet to reproduce:

# intersection profiling with Python session
from sage.all import *

def run(num):
    cube = (polytopes.cube() * 37 / 45).change_ring(QQ) 

    for i in range(num):
        hspace = Polyhedron(ieqs=[[1/2, 1/(i+1), 0, 0]]).change_ring(QQ)
        intersection = hspace.intersection(cube)

%timeit run(100)

The timing for SageMath kernel is 1 loop, best of 5: 186 ms per loop, while that for Python is 1 loop, best of 5: 7.07 s per loop. With this snippet I think no variable was cached. I also cprofiled a stand-alone .py file with the same lines (expect the %timeit line), whose timing is close to the Python kernel. Any idea what could cause this huge performance difference?

Image which kernel to use

edit retag flag offensive close merge delete

Comments

My env:

macOS 10.15.6 (RAM 16GB) SageMath 9.1

zhaiyu gravatar imagezhaiyu ( 2021-02-23 23:42:31 +0200 )edit

Can't reproduce : On my machine, I need abut 88 ms per loop in command line or through sage-shell-mode in emacs, and a bit less than 100 ms per loop in Jupyter (marginal and probably irrelevant difference...).

Emmanuel Charpentier gravatar imageEmmanuel Charpentier ( 2021-02-24 00:25:09 +0200 )edit
2

I don't think it's reasonable to compare a Python Jupyter notebook to SageNB: you should instead compare a SageMath Jupyter notebook to SageNB, in which case I don't see any significant time difference. (I do see a difference with a Python Jupyter notebook.)

John Palmieri gravatar imageJohn Palmieri ( 2021-02-24 01:35:09 +0200 )edit
1

Maybe one difference is that in a Sage notebook (SageNB or Jupyter), the numbers are treated as Sage integers, rationals, etc., while there is going to be a lot of coercion and conversion when you're dealing with a Python notebook. Just a guess.

John Palmieri gravatar imageJohn Palmieri ( 2021-02-24 01:36:28 +0200 )edit

For example, polytopes.cube() * 37/45 returns "A 3-dimensional polyhedron in RDF^3 ..." in a Python notebook while it returns "A 3-dimensional polyhedron in QQ^3 ..." in a Sage notebook.

John Palmieri gravatar imageJohn Palmieri ( 2021-02-24 01:40:20 +0200 )edit

1 Answer

Sort by » oldest newest most voted
1

answered 2021-02-24 18:07:13 +0200

zhaiyu gravatar image

updated 2021-02-24 18:08:45 +0200

Noted from John's comments, I can confirm the difference stems from the coercion and conversion stuff.

Given script.py and script.sage (same contents):

from sage.all import *
import time

def run(num):
    cube = (polytopes.cube() * 37 / 45).change_ring(QQ)

    for i in range(num):
        hspace = Polyhedron(ieqs=[[(i+1)/(i+2), 1/(i+1), (i+2), (i+53)]]).change_ring(QQ)
        intersection = hspace.intersection(cube)

tik = time.time()
run(100)
print('time elapsed: {}'.format(time.time() - tik), 's')

With python script.py, I got time elapsed: 8.750308990478516 s.

With sage script.sage, I got time elapsed: 0.6618611812591553 s, whose execution automatically generated a python file script.sage.py which looks like this:

# This file was *autogenerated* from the file profile.sage
from sage.all_cmdline import *   # import sage library

_sage_const_37 = Integer(37); _sage_const_45 = Integer(45); _sage_const_1 = Integer(1); _sage_const_2 = $
from sage.all import *
import time

def run(num):
    cube = (polytopes.cube() * _sage_const_37  / _sage_const_45 ).change_ring(QQ)

    for i in range(num):
        hspace = Polyhedron(ieqs=[[(i+_sage_const_1 )/(i+_sage_const_2 ), _sage_const_1 /(i+_sage_const_$
        intersection = hspace.intersection(cube)

tik = time.time()
run(_sage_const_100 )
print('time elapsed: {}'.format(time.time() - tik), 's')

I then ran python script.sage.py and got time elapsed: 0.6441857814788818 s.

This conversion is documented in the tutorial:

When Sage loads example.sage it converts it to Python, which is then executed by the Python interpreter. This conversion is minimal; it mainly involves wrapping integer literals in Integer() floating point literals in RealNumber(), replacing ^’s by **’s, and replacing e.g., R.2 by R.gen(2). The converted version of example.sage is contained in the same directory as example.sage and is called example.sage.py.

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2021-02-23 23:40:29 +0200

Seen: 460 times

Last updated: Feb 24 '21