-
-
Notifications
You must be signed in to change notification settings - Fork 10.9k
ENH: Remove NpyIter_Close #11376
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
ENH: Remove NpyIter_Close #11376
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1380,47 +1380,6 @@ NpyIter_GetInnerLoopSizePtr(NpyIter *iter) | |
} | ||
} | ||
|
||
/*NUMPY_API | ||
* Resolves all writebackifcopy scratch buffers, not safe to use iterator | ||
* operands after this call, in this iterator as well as any copies. | ||
* Returns 0 on success, -1 on failure | ||
*/ | ||
NPY_NO_EXPORT int | ||
NpyIter_Close(NpyIter *iter) | ||
{ | ||
int ret=0, iop, nop; | ||
PyArrayObject ** operands; | ||
npyiter_opitflags *op_itflags; | ||
if (iter == NULL) { | ||
return 0; | ||
} | ||
nop = NIT_NOP(iter); | ||
operands = NIT_OPERANDS(iter); | ||
op_itflags = NIT_OPITFLAGS(iter); | ||
/* If NPY_OP_ITFLAG_HAS_WRITEBACK flag set on operand, resolve it. | ||
* If the resolution fails (should never happen), continue from the | ||
* next operand and discard the writeback scratch buffers, and return | ||
* failure status | ||
*/ | ||
for (iop=0; iop<nop; iop++) { | ||
if (op_itflags[iop] & NPY_OP_ITFLAG_HAS_WRITEBACK) { | ||
op_itflags[iop] &= ~NPY_OP_ITFLAG_HAS_WRITEBACK; | ||
if (PyArray_ResolveWritebackIfCopy(operands[iop]) < 0) { | ||
ret = -1; | ||
iop++; | ||
break; | ||
} | ||
} | ||
} | ||
for (; iop<nop; iop++) { | ||
if (op_itflags[iop] & NPY_OP_ITFLAG_HAS_WRITEBACK) { | ||
op_itflags[iop] &= ~NPY_OP_ITFLAG_HAS_WRITEBACK; | ||
PyArray_DiscardWritebackIfCopy(operands[iop]); | ||
} | ||
} | ||
return ret; | ||
} | ||
|
||
/*NUMPY_API | ||
* For debugging | ||
*/ | ||
|
@@ -2830,4 +2789,23 @@ npyiter_checkreducesize(NpyIter *iter, npy_intp count, | |
} | ||
return count * (*reduce_innersize); | ||
} | ||
|
||
NPY_NO_EXPORT npy_bool | ||
npyiter_has_writeback(NpyIter *iter) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of this function, which traverses the flags a second time - can you just add an extra return value from Perhaps most simple would be to rename it to
Or perhaps even There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had considered that, but this API seems cleaner to me. Only the rarely used python We could revisit this idea in the future when the dust has settled around There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My fear with the current approach is that it separates the check of whether cleanup is needed from the actual code doing the cleanup.
It wouldn't surprise me if the compiler just inlined the outer function - assuming that we're using the internal function definition, rather than the external function pointer.
True, this PR as is is already a nice improvement |
||
{ | ||
int iop, nop; | ||
npyiter_opitflags *op_itflags; | ||
if (iter == NULL) { | ||
return 0; | ||
} | ||
nop = NIT_NOP(iter); | ||
op_itflags = NIT_OPITFLAGS(iter); | ||
|
||
for (iop=0; iop<nop; iop++) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit for future reference: should be spaces a round There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can be fixed up online before merge. |
||
if (op_itflags[iop] & NPY_OP_ITFLAG_HAS_WRITEBACK) { | ||
return NPY_TRUE; | ||
} | ||
} | ||
return NPY_FALSE; | ||
} | ||
#undef NPY_ITERATOR_IMPLEMENTATION_CODE |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -403,7 +403,6 @@ NpyIter_AdvancedNew(int nop, PyArrayObject **op_in, npy_uint32 flags, | |
*/ | ||
if (!npyiter_allocate_arrays(iter, flags, op_dtype, subtype, op_flags, | ||
op_itflags, op_axes)) { | ||
NpyIter_Close(iter); | ||
NpyIter_Deallocate(iter); | ||
return NULL; | ||
} | ||
|
@@ -465,14 +464,12 @@ NpyIter_AdvancedNew(int nop, PyArrayObject **op_in, npy_uint32 flags, | |
/* If buffering is set without delayed allocation */ | ||
if (itflags & NPY_ITFLAG_BUFFER) { | ||
if (!npyiter_allocate_transfer_functions(iter)) { | ||
NpyIter_Close(iter); | ||
NpyIter_Deallocate(iter); | ||
return NULL; | ||
} | ||
if (!(itflags & NPY_ITFLAG_DELAYBUF)) { | ||
/* Allocate the buffers */ | ||
if (!npyiter_allocate_buffers(iter, NULL)) { | ||
NpyIter_Close(iter); | ||
NpyIter_Deallocate(iter); | ||
return NULL; | ||
} | ||
|
@@ -654,6 +651,8 @@ NpyIter_Deallocate(NpyIter *iter) | |
int iop, nop; | ||
PyArray_Descr **dtype; | ||
PyArrayObject **object; | ||
npyiter_opitflags *op_itflags; | ||
npy_bool resolve = 1; | ||
|
||
if (iter == NULL) { | ||
return NPY_SUCCEED; | ||
|
@@ -663,6 +662,7 @@ NpyIter_Deallocate(NpyIter *iter) | |
nop = NIT_NOP(iter); | ||
dtype = NIT_DTYPES(iter); | ||
object = NIT_OPERANDS(iter); | ||
op_itflags = NIT_OPITFLAGS(iter); | ||
|
||
/* Deallocate any buffers and buffering data */ | ||
if (itflags & NPY_ITFLAG_BUFFER) { | ||
|
@@ -691,15 +691,28 @@ NpyIter_Deallocate(NpyIter *iter) | |
} | ||
} | ||
|
||
/* Deallocate all the dtypes and objects that were iterated */ | ||
/* | ||
* Deallocate all the dtypes and objects that were iterated and resolve | ||
* any writeback buffers created by the iterator | ||
*/ | ||
for(iop = 0; iop < nop; ++iop, ++dtype, ++object) { | ||
if (op_itflags[iop] & NPY_OP_ITFLAG_HAS_WRITEBACK) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For consistency with how Probably not worth it though - if anything I find your approach clearer. |
||
if (resolve && PyArray_ResolveWritebackIfCopy(*object) < 0) { | ||
resolve = 0; | ||
} | ||
else { | ||
PyArray_DiscardWritebackIfCopy(*object); | ||
} | ||
} | ||
Py_XDECREF(*dtype); | ||
Py_XDECREF(*object); | ||
} | ||
|
||
/* Deallocate the iterator memory */ | ||
PyObject_Free(iter); | ||
|
||
if (resolve == 0) { | ||
return NPY_FAIL; | ||
} | ||
return NPY_SUCCEED; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't the code below need to move into
NpyIter_Dealloc
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it now lives inside
NpyIter_Deallc
. Comment expanded to emphasize that.