8000 Sag handle numerical error outside of cython by pierreglaser · Pull Request #13389 · scikit-learn/scikit-learn · GitHub
[go: up one dir, main page]

Skip to content

Sag handle numerical error outside of cython #13389

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

pierreglaser
Copy link
Contributor
@pierreglaser pierreglaser commented Mar 4, 2019

Closes #13316

Cython's gcc branch prediction directive make sag unnecessarily fight for the GIL at a high frequency in case an error needs to be raised. This severely impacts the performance of parallel sag calls using a joblib "threading" backend.

I propose to handle numerical error "C-style", by propagating return codes and breaking out of for-loops. An error is raised once and for all after sag, in sag_solver.

Note that I need to manually break out of for-loops and not simply return -1 after the check, as returning requires the GIL, so the same problem would happen.

@jeremiedbb followed the issue during last sprint.

Copy link
Member
@jeremiedbb jeremiedbb left a comment

Choose a reason for hiding this comment

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

looks good.

just a couple of minor comments.

Also can you run the benchmark #13316 with this change ?

@pierreglaser
Copy link
Contributor Author

Running the same #13316 benchmark, I now get:

backend: threading n_jobs: 1 total time: (6.028,  n_iter: 15.0)
backend: threading n_jobs: 2 total time: (3.815,  n_iter: 15.6)
backend: threading n_jobs: 4 total time: (3.018,  n_iter: 15.8)
backend:      loky n_jobs: 1 total time: (6.448,  n_iter: 15.3)
backend:      loky n_jobs: 2 total time: (4.532,  n_iter: 15.4)
backend:      loky n_jobs: 4 total time: (3.255,  n_iter: 15.3)

Copy link
Member
@TomDLT TomDLT left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor
@massich massich left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Member
@ogrisel ogrisel left a comment

Choose a reason for hiding this comment

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

This is a really weird performance bug. Have you tried to re-run your benchmark with this PR to confirm that it fixes the performance issue observed with the threading backend?

Can you try to compile this extension without branch prediction to confirm that the GIL acquisition is caused by this as suggested in #13316 (comment)? That sounds really weird to me.

@jeremiedbb
Copy link
Member

This is a really weird performance bug. Have you tried to re-run your benchmark with this PR to confirm that it fixes the performance issue observed with the threading backend?

just look a bit above :)

@jeremiedbb
Copy link
Member

Can you try to compile this extension without branch prediction to confirm that the GIL acquisition is caused by this as suggested in #13316 (comment)? That sounds really weird to me.

This is strange indeed but if you comment the

if something_not_finite:
    with gil:
        raise error

bloks, the issue disappears, although the condition is never met (because no error is raised)

@pierreglaser
Copy link
Contributor Author

@ogrisel I tried disabling Cython.Compiler.Options.gcc_branch_hints using current master but that did not improve performance.
However, not trying to aquire the gil in such setting is not unusual: in sgd_fast.pyx, the same "trick" is done:

# floating-point under-/overflow check.
if (not skl_isfinite(intercept)
or any_nonfinite(<double *>weights.data, n_features)):
infinity = True
break

then further along the way:

8000
if infinity:
raise ValueError(("Floating-point under-/overflow occurred at epoch"
" #%d. Scaling input data with StandardScaler or"
" MinMaxScaler might help.") % (epoch + 1))

@jeremiedbb
Copy link
Member

I tried disabling Cython.Compiler.Options.gcc_branch_hints

these are just hints but I think it does not disable branch prediction. Branch prediction is done by the cpu. I can't see how to disable it.

Copy link
Member
@ogrisel ogrisel left a comment

Choose a reason for hiding this comment

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

nitpick but otherwise looks good to me!

I suppose we might want to set prefer="threads" for LogisticRegressionCV when the saga solver is used but this should probably be done elsewhere.

@ogrisel ogrisel merged commit 0f0799a into scikit-learn:master Mar 6, 2019
@wamuir
Copy link
wamuir commented Mar 10, 2019

So much better. Thank you @pierreglaser

xhluca pushed a commit to xhluca/scikit-learn that referenced this pull request Apr 28, 2019
xhluca pushed a commit to xhluca/scikit-learn that referenced this pull request Apr 28, 2019
xhluca pushed a commit to xhluca/scikit-learn that referenced this pull request Apr 28, 2019
koenvandevelde pushed a commit to koenvandevelde/scikit-learn that referenced this pull request Jul 12, 2019
@jeremiedbb jeremiedbb mentioned this pull request Dec 17, 2021
4 tasks
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
0