Skip to content
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

exposed llvm lambdify opt_level in python api #300

Merged
merged 5 commits into from Sep 20, 2019

Conversation

ichumuh
Copy link

@ichumuh ichumuh commented Sep 16, 2019

As requested by me in symengine/symengine#1612. Do you think it look good?
@isuruf can you please merge isuruf/symengine@ac7b9bb as well?

@certik
Copy link
Contributor

certik commented Sep 17, 2019

Would you mind adding a test for this flag please? It would go somewhere in https://github.com/symengine/symengine.py/blob/8909cff0f1087a6e743821b580531d5b02f04b74/symengine/tests/test_lambdify.py.

@ichumuh
Copy link
Author

ichumuh commented Sep 17, 2019

To do this test properly, I'd have to check if the opt_level actually works, right? The only why I can think of right now would be to compair runtimes, but that doesn't seem clean to me. Do you have a better idea? Or do I just test if it doesn't throw errors?

@certik
Copy link
Contributor

certik commented Sep 17, 2019

I would just test that the opt_level can be passed in. It's our responsibility in the C++ symengine to ensure it actually works.

@ichumuh
Copy link
Author

ichumuh commented Sep 18, 2019

I currently have added opt_level to LLVMDouble, LambdaDouble and _Lambdify.
But we actually only need it for LLVMDouble. Would it be better to only add it to that class and to use something as default, when Lambdify is used?

@bjodah
Copy link
Contributor

bjodah commented Sep 18, 2019

Yes, let's make sure that passing opt_level to LambdaDouble throws an exception.

@ichumuh
Copy link
Author

ichumuh commented Sep 18, 2019

So should Lambdify accept opt_level or not? It seems to me like LLVMDouble is not intended to be used directly.

@bjodah
Copy link
Contributor

bjodah commented Sep 18, 2019

Have it accept **kwargs? anf if backend=="llvm" then opt_level can be popped out of kwargs (opt_level=kwargs.pop("opt_level", 3) and at end of init we always check that kwargs is empty, and if not: raise an exception)

@isuruf
Copy link
Member

isuruf commented Sep 18, 2019

Yes, but if the backend is lambda, we should check that opt_level is None. If the backend is lambda and opt_level is None, opt_level=3 should be passed. If the backend is lambda and opt_level is not None, value should be passed through.

@ichumuh
Copy link
Author

ichumuh commented Sep 18, 2019

@isuruf you meant llvm instead of lambda right?

@isuruf
Copy link
Member

isuruf commented Sep 18, 2019

Yes, @bjodah's proposal sounds better to me though.

@ichumuh
Copy link
Author

ichumuh commented Sep 18, 2019

How about this? __init__ in _Lambdify accepts kwargs as well and I use __cinit__ in LambdaDouble and LLVMDouble to extract needed parameters. Lambdify can just pass kwargs. This automatically gives me an error, when I use opt_level with backend lambda for example.

@bjodah
Copy link
Contributor

bjodah commented Sep 18, 2019

That looks good, but perhaps the default should be higher than 0? (we should probably gather some benchmarks for LLVMDouble eventually)

We can also check that it's given a valid value:

if not 0<=opt_level<=3:
    raise ValueError("opt_level needs to be 0, 1, 2 or 3, got: %s" % str(opt_level))

(or we make sure this check is done on the C++ side)

@ichumuh
Copy link
Author

ichumuh commented Sep 18, 2019

That looks good, but perhaps the default should be higher than 0? (we should probably gather some benchmarks for LLVMDouble eventually)

Sure, I'll make it 3 again and write some tests.

We can also check that it's given a valid value:

I think the c++ side should do this check, maybe the range will change at some point.

@ichumuh
Copy link
Author

ichumuh commented Sep 18, 2019

We can also check that it's given a valid value:

if not 0<=opt_level<=3:
    raise ValueError("opt_level needs to be 0, 1, 2 or 3, got: %s" % str(opt_level))

(or we make sure this check is done on the C++ side)

It currently seems like there is only a difference between 0 and not 0, all negative and positive always seem to produce the same numbers. I don't know why 3 is the default in the C++ api. Maybe it's because I'm using llvm 8.0?

@bjodah
Copy link
Contributor

bjodah commented Sep 18, 2019

Maybe the cost/benefit ratio depends on the type of expression? e.g. if there are many Piecewise objects (but it's just guesswork on my part).

I don't remember what the story was for auto-vectorization for example. But it would be nice if such optimizations were possible (in the future), but that's off topic for this PR of course. But since I'm already digressing, this gets me thinking: I don't think LLVM comes with approximate transcendentals(?), intel's compiler has such a flag:
https://software.intel.com/en-us/cpp-compiler-developer-guide-and-reference-fast-transcendentals-qfast-transcendentals
such optimizations would also be a pretty nice option once/if llvm supports them.

EDIT: looks like Intel's libsvml can be used (but that's closed source), SLEEF was suggested as an open source vectorized math lib for llvm, but it doesn't look like the PR was merged.

@ichumuh
Copy link
Author

ichumuh commented Sep 19, 2019

How do I actually run the tests? When I'm doing py.test -v symengine/tests/test_*.py I get

ImportError while importing test module '/home/stelter/my_symengine/symengine.py/symengine/tests/test_var.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
symengine/__init__.py:1: in <module>
    from .lib.symengine_wrapper import (
E   ImportError: No module named symengine_wrapper

While inside of this folder I also can't import symengine in ipython, it throws the same error.
When I'm in a different folder, symengine works though.

@ichumuh
Copy link
Author

ichumuh commented Sep 19, 2019

Nvm, the tests work when I'm in /usr/local/lib/python2.7/dist-packages and do py.test -v symengine/tests/test_*.py

@ichumuh
Copy link
Author

ichumuh commented Sep 19, 2019

Are these tests sufficient?

@bjodah
Copy link
Contributor

bjodah commented Sep 19, 2019

+1 from me.
And thank you for working on this!

Copy link
Contributor

@certik certik left a comment

Choose a reason for hiding this comment

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

That looks good, thanks!

@bjodah bjodah merged commit 7dd26e0 into symengine:master Sep 20, 2019
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.

None yet

4 participants