First time here? Check out the FAQ!

Ask Your Question
1

Python kernel seriously slower than SageMath kernel

asked 4 years ago

zhaiyu gravatar image

updated 4 years ago

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

Preview: (hide)

Comments

My env:

macOS 10.15.6 (RAM 16GB) SageMath 9.1

zhaiyu gravatar imagezhaiyu ( 4 years ago )

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 ( 4 years ago )
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 ( 4 years ago )
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 ( 4 years ago )

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 ( 4 years ago )

1 Answer

Sort by » oldest newest most voted
1

answered 4 years ago

zhaiyu gravatar image

updated 4 years ago

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.

Preview: (hide)
link

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: 4 years ago

Seen: 655 times

Last updated: Feb 24 '21