numpy.shares_memory和numpy.may_share_memory有什么区别?

gle*_*oux 8 python numpy

为什么numpy.may_share_memory存在?
给出确切结果的挑战是什么?

numpy.may_share_memory弃用的方法?
numpy.may_share_memory可能会给出误报,但不会给出假阴性.

没有人numpy.shares_memory给出假阳性而没有假阴性吗?

我使用numpy版本1.11.2.

看到:

  1. numpy.may_share_memory
  2. numpy.shares_memory
  3. github上的1.11.2版源代码

And*_*eak 10

引用1.11.0发行说明:

添加了一个新函数np.shares_memory,可以准确检查两个数组是否有内存重叠.np.may_share_memory现在也可以选择花更多的精力来减少误报.

从语义上讲,这表明较旧的may_share_memory测试旨在得到一个宽松的猜测是否在阵列之间共享内存.如果肯定不是,那么可以相应地进行.如果有阳性检测(可能是假阳性),则必须小心.shares_memory另一方面,新功能允许精确检查.这需要更多的计算时间,但从长远来看可能是有益的,因为没有误报可以使用更多可能的优化.更宽松的检查may_share_memory可能只保证不会返回假阴性.

在文档方面may_share_memoryshares_memory,都有一个关键字参数,告诉numpy的用户进行检查严格程度要.

may_share_memory:

max_work : int, optional

    Effort to spend on solving the overlap problem. See shares_memory for details. Default for may_share_memory is to do a bounds check.
Run Code Online (Sandbox Code Playgroud)

shares_memory:

max_work : int, optional

    Effort to spend on solving the overlap problem (maximum number of candidate solutions to consider). The following special values are recognized:

    max_work=MAY_SHARE_EXACT (default)

        The problem is solved exactly. In this case, the function returns True only if there is an element shared between the arrays.
    max_work=MAY_SHARE_BOUNDS

        Only the memory bounds of a and b are checked.
Run Code Online (Sandbox Code Playgroud)

从文档来看,这表明这两个函数可能会调用相同的底层机制,但may_share_memory使用不太严格的默认设置进行检查.

让我们来看看实现:

static PyObject *
array_shares_memory(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
{
    return array_shares_memory_impl(args, kwds, NPY_MAY_SHARE_EXACT, 1);
}


static PyObject *
array_may_share_memory(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
{
    return array_shares_memory_impl(args, kwds, NPY_MAY_SHARE_BOUNDS, 0);
}
Run Code Online (Sandbox Code Playgroud)

使用签名调用相同的底层函数

static PyObject *
array_shares_memory_impl(PyObject *args, PyObject *kwds, Py_ssize_t default_max_work,
                         int raise_exceptions)
{}
Run Code Online (Sandbox Code Playgroud)

如果不深入研究源代码,在我看来这shares_memory是一个改进may_share_memory,它可以使用适当的关键字参数进行与后者相同的松散检查.较旧的功能可用于方便和向后兼容.

免责声明:这是我第一次看到源代码的这一部分,而我没有进一步调查array_shares_memory_impl,所以我的印象可能完全错误.


至于两个方法之间差异的具体示例(使用默认参数调用):在上面的链接中解释了may_share_memory它只检查数组绑定索引.如果它们是不相交的两个数组,然后有没有机会,他们可以共享内存.但如果它们不是不相交的,那么阵列仍然是独立的!

简单示例:通过切片对连续的内存块进行不相交的分区:

>>> import numpy as np
>>> v = np.arange(6)
>>> x = v[::2]
>>> y = v[1::2]
>>> np.may_share_memory(x,y)
True
>>> np.shares_memory(x,y)
False
>>> np.may_share_memory(x,y,max_work=np.MAY_SHARE_EXACT)
False
Run Code Online (Sandbox Code Playgroud)

如您所见,x并且y是同一阵列的两个不相交的切片.因此,它们的数据范围在很大程度上重叠(它们几乎相同,在内存中保存一个整数).但是,它们的元素实际上都不相同:一个包含偶数,另一个包含原始连续块的奇数元素.因此,may_share_memory正确断言数组可能共享内存,但在更严格的检查中,事实证明它们没有.


至于精确计算重叠的额外难度,可以将工作追溯到被调用的工作人员solve_may_share_memory,其中还包含许多有关正在发生的事情的有用评论.简而言之,就是这样

  1. a quick check and return如果边界重叠,否则
  2. 一个有回报MEM_OVERLAP_TOO_HARD,如果我们要求宽松检查(即may_share_memory使用默认参数),这是主叫方的处理是"我们不知道,所以返回True"
  3. 否则我们实际上解决了问题映射到此处的丢番图方程

因此,上面第3点的工作是需要另外完成的工作shares_memory(或者通常是严格的检查案例).