Skip to content

Split CPython and begin the Cython revolution - #1595

Merged
ctb merged 66 commits into
masterfrom
feature/cython_all_the_things
May 31, 2017
Merged

ctb merged 66 commits into
masterfrom
feature/cython_all_the_things

Conversation

@camillescott

@camillescott camillescott commented Jan 26, 2017 •

Copy link
Copy Markdown
Member
  • Is it mergeable?
  • make test Did it pass the tests?
  • make clean diff-cover If it introduces new functionality in
    scripts/ is it tested?
  • make format diff_pylint_report cppcheck doc pydocstyle Is it well
    formatted?
  • Did it change the command-line interface? Only backwards-compatible
    additions are allowed without a major version increment. Changing file
    formats also requires a major version number increment.
  • For substantial changes or changes to the command-line interface, is it
    documented in CHANGELOG.md? See keepachangelog
    for more details.
  • Was a spellchecker run on the source code and documentation after
    changes were made?
  • Do the changes respect streaming IO? (Are they
    tested for streaming IO?)

Comment thread setup.py Outdated

CMDCLASS = versioneer.get_cmdclass()

from Cython.Build import cythonize

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recent setuptools (>18.0) can detect if Cython is installed, so no need to import Cython. This is the line that makes it work (in sourmash): https://github.com/dib-lab/sourmash/blob/9b9f7f467b9e99a4bba2e73869058da6021a0835/setup.py#L67

@standage

Copy link
Copy Markdown
Member

Note, if #1597 is merged before this is, I'll be happy to take the first stab at resolving the merge conflicts while the changes are still fresh in my head.

@betatim

betatim commented Jan 27, 2017

Copy link
Copy Markdown
Member

Considering how much we have discussed making small movements and avoiding change for changes sake: Is this the minimal PR needed to start using cython for the python <-> c++ bridge?

@ctb

ctb commented Jan 27, 2017

Copy link
Copy Markdown
Member

@betatim from casual offline conversations, it seems like the big problem was resolving the borked way that I/we wrote CPython using lot of static declarations (as recommended in the CPython documentation, sigh). So this is mostly a reorganization of khmer/ code.

Since the tests are not changed at all, I am reasonably confident about the prospect of merging it, but that will have to wait until 2.1 comes out in any case.

@betatim

betatim commented Jan 27, 2017

Copy link
Copy Markdown
Member

A more constructive comment: my idea of a gentle transition from the current CPython wrapper to one based on cython would be to pick one of the khmer classes, remove the CPython wrapper and replace it by cython. Merge, repeat for the next class.

In this PR we have:

  • reorganisation of the CPython code,
  • addition of an assembler, and
  • addition of a wrapper for khmer classes in the oxli namespace.

From the viewpoint of a reviewer it is essentially impossible to tell where code was moved, modified, deleted or added. A huge amount of work has gone into this so it deserves a better review than "travis seems happy so let's merge".

@ctb

ctb commented Jan 27, 2017 via email

Copy link
Copy Markdown
Member

@betatim

betatim commented Jan 27, 2017 •

Copy link
Copy Markdown
Member

Can't we delete some of the CPython wrapper? If we add a cython bridge to the c++ we now have two bridges to keep in sync. So why not get rid of the old one?

In order not to have to instantly rewrite all the scripts we can add
from oxli import Counttable (etc) to khmer/__init__.py so we maintain the khmer namespace for a bit, before it becomes deprecated.

@camillescott

camillescott commented Jan 27, 2017 via email

Copy link
Copy Markdown
Member Author

@codecov-io

codecov-io commented Jan 30, 2017 •

Copy link
Copy Markdown

Codecov Report

Merging #1595 into master will decrease coverage by 64.01%.
The diff coverage is 0%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #1595       +/-   ##
==========================================
- Coverage   64.06%   0.05%   -64.02%     
==========================================
  Files          79      91       +12     
  Lines       12203   11500      -703     
  Branches     3085    3063       -22     
==========================================
- Hits         7818       6     -7812     
- Misses       2675   11494     +8819     
+ Partials     1710       0     -1710
Impacted Files Coverage Δ
include/oxli/read_aligner.hh 0% <ø> (ø)
khmer/thread_utils.py 0% <ø> (-93.34%) ⬇️
scripts/unique-kmers.py 0% <ø> (-97.88%) ⬇️
scripts/find-knots.py 0% <ø> (-98.51%) ⬇️
scripts/load-into-counting.py 0% <ø> (-97.83%) ⬇️
src/khmer/_cpy_smallcounttable.cc 0% <ø> (ø)
include/oxli/subset.hh 0% <ø> (ø)
scripts/split-paired-reads.py 0% <ø> (-96.21%) ⬇️
oxli/build_graph.py 0% <ø> (-96.08%) ⬇️
scripts/count-median.py 0% <ø> (-90.7%) ⬇️
... and 139 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update c46dbed...2431698. Read the comment docs.

@camillescott

Copy link
Copy Markdown
Member Author

Odd, when I made previous comment it was directed at @standage, none of @betatim's comments had appeared in my inbox.

So, I'll point out that the assembler is not new; it already has a CPython wrapper. Regardless, point taken. Unfortunately, the "minimal" PR to convert is necessarily quite large either way, as it requires splitting up the CPython stuff and adding all the definitions in _oxli.pxd. I suppose if one was so inclined, they could merge in the CPython slicing and dicing to a new PR.

@camillescott

Copy link
Copy Markdown
Member Author

Also: for now I haven't wrapped the entirety of Hashgraph; it's only available within the Cython wrapper. That would considerably increase the code size. The Assembler is in there as a proof of concept for taking incremental steps: it takes an old-style CPython Nodegraph object.

@betatim

betatim commented Jan 31, 2017

Copy link
Copy Markdown
Member

So how do we go about merging this? Are there more things that need to be added or should we fix the merge conflicts, review it, travis it, merge it?

What are your opinions on starting to get rid of the CPython wrapper code? My vote would be to write a cython wrapper in oxli, remove the CPython code, in khmer replace things with imports from oxli, and in the scripts switch to importing from oxli directly. Do this in a new PR (for N classes at a time).

@betatim

betatim commented Jan 31, 2017

Copy link
Copy Markdown
Member

Another thing that might become possible/easier after this PR is to try and find all the instances where a new string object is created but doesn't have to. Once we read a bit of sequence in, we should never have to copy it. Related question, can we keep things as bytes and save ourselves encoding/decoding steps?

@ctb

ctb commented Jan 31, 2017 via email

Copy link
Copy Markdown
Member

@camillescott

Copy link
Copy Markdown
Member Author

Issues re: the new release are another reason why I didn't remove parts of the CPython wrapper. I figured if it stays on its own it can be merged whenever, and just be there in the background.

@camillescott

Copy link
Copy Markdown
Member Author

It does occur to me that the stuff in parsing.pyx should be done separately though. It replaces ReadParser and broken_paired_reader with faster versions.

@ctb

ctb commented Jan 31, 2017

Copy link
Copy Markdown
Member

What problems are there with:

  • completely removing the CPython layer in this PR;
  • updating incrementally from master as we move towards 2.1;
  • merging immediately after 2.1 release;

?

@camillescott

camillescott commented Jan 31, 2017 via email

Copy link
Copy Markdown
Member Author

@ctb

ctb commented Jan 31, 2017 via email

Copy link
Copy Markdown
Member

@ctb

ctb commented Feb 1, 2017

Copy link
Copy Markdown
Member

So @camillescott and I talked a bit about this today, and it seems like there are a few things going on. Hopefully she can correct me if I get this wrong --

The JunctionCountAssembler stuff is wrapped in Cython. That's fine, nothing relies on it yet, +1.

There's a bunch of Cython declarations (but not wrapping) for the existing CPython interface.
This lets us use it from Cython but doesn't redefine it. This is a conservative move, +1.

Then there is some "old" stuff (C++ and Python) that got reimplemented as Cython inside of oxli - hashing.pyx, parsing.pyx, traversal.pyx. I think this stuff is a bit dangerous because AFAICT it now provides functionality & code that exists in two places. I'm not sure what to do about this; I can't assess on a quick scan how easy it is to put into a different PR or how much stuff in this PR depends on it.

(Above, all that "update incrementally" means is that as we add new stuff before releasing 2.1, we update this branch.)

@ctb

ctb commented May 23, 2017

Copy link
Copy Markdown
Member

How do you feel about merging in #1590? That's gotta happen at some point...

@ctb

ctb commented May 23, 2017

Copy link
Copy Markdown
Member

(I can update it from master if you like.)

@camillescott

camillescott commented May 23, 2017 via email

Copy link
Copy Markdown
Member Author

@ctb

ctb commented May 23, 2017 via email

Copy link
Copy Markdown
Member

@camillescott

Copy link
Copy Markdown
Member Author

I mean, sure, go ahead. I'm -1 on making merger of this contingent on merger of the many other open PRs that are up currently though... seems like a roundabout way of doing things.

@ctb

ctb commented May 23, 2017 via email

Copy link
Copy Markdown
Member

@camillescott

camillescott commented May 24, 2017 via email

Copy link
Copy Markdown
Member Author

@betatim

betatim commented May 26, 2017

Copy link
Copy Markdown
Member

Taking a look at the failing cpp-demos

@betatim

betatim commented May 26, 2017

Copy link
Copy Markdown
Member

I had to apply the following to get things to compile on my mac:

@@ -67,6 +67,7 @@ CMDCLASS = versioneer.get_cmdclass()
 HAS_CYTHON = False
 try:
     import Cython
+    from Cython.Build import cythonize
     HAS_CYTHON = True
 except ImportError:
     pass
@@ -194,6 +195,7 @@ CP_EXTENSION_MOD_DICT = \
 
 EXTENSION_MODS = [Extension("khmer._khmer", ** CP_EXTENSION_MOD_DICT)]
 
+mods = []
 for cython_ext in glob.glob(os.path.join("khmer", "_oxli",
                                          "*.{0}".format(cy_ext))):
 
@@ -212,7 +214,10 @@ for cython_ext in glob.glob(os.path.join("khmer", "_oxli",
 
     ext_name = "khmer._oxli.{0}".format(
         splitext(os.path.basename(cython_ext))[0])
-    EXTENSION_MODS.append(Extension(ext_name, ** CY_EXTENSION_MOD_DICT))
+    mods.append(Extension(ext_name, ** CY_EXTENSION_MOD_DICT))
+
+EXTENSION_MODS.extend(cythonize(mods))
 
 SCRIPTS = []
 SCRIPTS.extend([path_join("scripts", script)

but travis seems happy without??

@betatim

betatim commented May 29, 2017

Copy link
Copy Markdown
Member

The above modification to setup.py only seems to be needed on my mac, at least on my linux machine this branch "just works".

@camillescott

Copy link
Copy Markdown
Member Author

You must have an outdated setuptools -- new versions support cython out of the box. Seems we should update the requirements file to reflect that.

@camillescott

Copy link
Copy Markdown
Member Author

ready for review comrades @ctb @standage

@ctb ctb left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let the Cython revolution begin!

@ctb
ctb merged commit 4fc53f6 into master May 31, 2017
@ctb

ctb commented May 31, 2017

Copy link
Copy Markdown
Member

Unleash the Cython!

@ctb

ctb commented May 31, 2017

Copy link
Copy Markdown
Member

@luizirber (for one) welcomes our new Cython overlords!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants