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

Update ufunc override to work properly with ufunc methods. #4626

Merged
merged 3 commits into from May 15, 2014

Conversation

cowlicks
Copy link
Contributor

This allows the ufunc override machinery to work properly with all the ufunc methods.

There is one failing test here which I am looking into. It passes for some python versions and not others.

The ufunc methods required some API design decisions and I'd like to hear what people think. The original ufunc override spec called for the arguments to be parsed into inputs and kwargs. But what is an input and what is a kwarg?

The methods I'm wondering about are ufunc.outer(A, B) and ufunc.at(a, indices[, b]).
For outer I guess both A and B should be in inputs? For at should b also be in inputs.

Also please check my reference counting, I'm not confident about it.

@cowlicks
Copy link
Contributor Author

This fixes the bug mentioned here.

@@ -4939,6 +4949,20 @@ ufunc_at(PyUFuncObject *ufunc, PyObject *args)
char * err_msg = NULL;
NPY_BEGIN_THREADS_DEF;

/* override vars */
int errval;
Copy link
Member

Choose a reason for hiding this comment

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

Need to declare before NPY_BEGIN_THREADS_DEF;, which has an empty statement before; and makes this declaration after a code statement. This is an error on windows also.

@charris
Copy link
Member

charris commented Apr 20, 2014

Bunch of warnings like this

numpy/core/src/private/ufunc_override.h:270:16: warning: comparison with string literal results in unspecified behavior [-Waddress]

Might be related to the almost universal test failures.

When you are ready, could you clean up the commit history and messages? Messages like Better tests for ufunc.method overrides. are not very informative. There should be a description of what is done and what problem it solves.

@charris
Copy link
Member

charris commented Apr 23, 2014

All compiled and ran, but all had failures.

method_name = PyUString_FromString(method);
if (method_name == NULL) {
/* ufunc.reduce */
else if (strncmp(method, "reduce", 6) == 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

this also catches "reduceat"
maybe an enum is more appropriate

@cowlicks
Copy link
Contributor Author

@juliantaylor good catch, I'll do that when I get a chance.

@charris I'll rebase with the appropriate BUG/ENH formatting once I get all these failures sorted out.

@cowlicks
Copy link
Contributor Author

Any clue about the segfault?
https://travis-ci.org/numpy/numpy/jobs/24039989

else {
/* keepdims */
PyDict_SetItemString(*normal_kwds, "keepdims", obj);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do I need to Py_DECREF(obj) here (and other places)? I'm not sure if PyDict_SetItemString has its own reference to obj now.

@seberg
Copy link
Member

seberg commented Apr 30, 2014

Don't know that much debugging foo, but did you try running the test in valgrind (best selectively just that file with runtests maybe, it is slow)? valgrind --suppressions=python.supp command. You can actually get some hint on finding dangling references using valgrind --suppressions=python.supp --track-origins=yes --leak-check=yes --show-possibly-lost=no command. I bet there are better ways though... You can try sebastian.sipsolutions.net/python.supp for a suppressions file (it should remove a lot of spam due to how python allocates stuff).

@@ -4939,6 +4954,15 @@ ufunc_at(PyUFuncObject *ufunc, PyObject *args)
char * err_msg = NULL;
NPY_BEGIN_THREADS_DEF;

/* `nin`, the last arg, is unused. So we put 0. */
errval = PyUFunc_CheckOverride(ufunc, "at", args, kwds, &override, 0);
Copy link
Contributor

Choose a reason for hiding this comment

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

kwds is uninitialized here, probably the cause of the segfault

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, that was it. Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

now theres a memory leak, why not simply pass in NULL?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done, thanks.

@cowlicks
Copy link
Contributor Author

cowlicks commented May 1, 2014

@charris Rebased with proper commit messages.

@charris
Copy link
Member

charris commented May 4, 2014

@pv Does this LGTY.

assert_equal(res[4], (1, a))
assert_equal(res[5], {})

res = np.multiply.reduce(a, 'axis0', 'dtype0', 'out0', 'keep0')
Copy link
Member

Choose a reason for hiding this comment

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

No tests with kwargs --- these check just that the positional args work ok.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Working on it. I implemented at with the last arg as a kwarg which is incorrect.

Copy link
Member

Choose a reason for hiding this comment

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

What state is master in if this doesn't get merged? Would leaving this out
of 1.9 mean that we release 1.9 with a broken numpy_ufunc API and get
stuck in some compatibility trap?

On Fri, May 9, 2014 at 8:34 PM, Blake Griffith notifications@github.comwrote:

In numpy/core/tests/test_umath.py:

- assert_equal(res, "reduce")

  •    res = np.multiply.accumulate(a, 1)
    

- assert_equal(res, "accumulate")

  •    res = np.multiply.reduceat(a, 1)
    
  •    assert_equal(res, "reduceat")
    
  •    res = np.multiply.**call**(1, a)
    
  •    assert_equal(res[0], a)
    
  •    assert_equal(res[1], np.multiply)
    
  •    assert_equal(res[2], '**call**')
    
  •    assert_equal(res[3], 1)
    
  •    assert_equal(res[4], (1, a))
    
  •    assert_equal(res[5], {})
    
  •    res = np.multiply.reduce(a, 'axis0', 'dtype0', 'out0', 'keep0')
    

Working on it. I implemented at with the last arg as a kwarg which is
incorrect.


Reply to this email directly or view it on GitHubhttps://github.com//pull/4626/files#r12492498
.

Nathaniel J. Smith
Postdoctoral researcher - Informatics - University of Edinburgh
http://vorpus.org

Copy link
Member

Choose a reason for hiding this comment

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

In master: if ufuncs are given extra optional arguments as positional arguments --- apart from the input and out= one --- they are stuffed to out kwarg instead of separate kwargs in master.

While this is buggy in itself, it is in practice perhaps not a common situation. (As the ufunc extra args are obscure stuff, people tend to call them as kwargs.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@pv kwargs tests added.

Copy link
Contributor

Choose a reason for hiding this comment

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

are the non reduce kwargs tested? extobj, where, casting etc?

@charris
Copy link
Member

charris commented May 4, 2014

I'm going to branch 1.9.x today, and wait a few days for 1.9.0. This can be backported if it is ready in time.

@juliantaylor
Copy link
Contributor

the non-reduce kwargs cannot be passed positionally, so its probably fine
I'm going to merge it today

@juliantaylor
Copy link
Contributor

merging, thanks

juliantaylor added a commit that referenced this pull request May 15, 2014
Update ufunc override to work properly with ufunc methods.
@juliantaylor juliantaylor merged commit 003fcda into numpy:master May 15, 2014
@cowlicks cowlicks deleted the ufunc-override-methods branch May 16, 2014 02:13
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

6 participants