首页 > 解决方案 > ND4J 切片是否会复制原始数组?

问题描述

ND4JINDArray切片是通过javaget()中回答的一种重载方法实现的- 获取 Nd4j 数组的任意切片 - 代码日志。作为INDArray一个连续的本机内存块,使用切片是否get()会复制原始内存(尤其是行切片,其中可以创建一个INDArray具有相同后备内存的新内存)?

我找到了另一种INDArray方法subArray()。这个有什么区别吗?

我问这个是因为我正在尝试创建一个DatasetIterator可以直接从INDArrays 中提取数据的程序,并且我想消除可能的开销。源代码中有太多抽象,我自己找不到实现。

在python - Numpy: views vs copy by slicing - Stack Overflow中提出了一个关于 NumPy 的类似问题,答案可以在Indexing - NumPy v1.16 Manual中找到:

这里的经验法则可以是:在左值索引的上下文中(即索引放置在赋值的左侧值中),不创建数组的视图或副本(因为没有必要)。但是,对于常规值,上述创建视图的规则确实适用。

标签: slicedeeplearning4jdl4jnd4j

解决方案


简短的回答是:不,它尽可能使用参考。要进行复制,.dup()可以调用该函数。

引用https://deeplearning4j.org/docs/latest/nd4j-overview

视图:当两个或多个 NDArray 引用相同的数据时

ND4J 中的一个关键概念是两个 NDArrays 实际上可以指向内存中相同的底层数据。通常,我们有一个 NDArray 引用另一个数组的某个子集,并且这只发生在某些操作中(例如 INDArray.get()、INDArray.transpose()、INDArray.getRow() 等。这是一个强大的概念,并且一个值得理解的。

这样做的主要动机有两个:

有相当大的性能优势,尤其是在避免复制数组方面我们在如何对 NDArray 执行操作方面获得了很多能力考虑一个简单的操作,例如在大型 (10,000 x 10,000) 矩阵上进行矩阵转置。使用视图,我们可以在恒定时间内执行此矩阵转置,而无需执行任何复制(即大 O 表示法中的 O(1)),从而避免复制所有数组元素的巨大成本。当然,有时我们确实想要制作一个副本——此时我们可以使用 INDArray.dup() 来获取一个副本。例如,要获取转置矩阵的副本,请使用 INDArray out = myMatrix.transpose().dup()。在此 dup() 调用之后,原始数组 myMatrix 和数组 out 之间将没有链接(因此,对其中一个的更改不会影响另一个)。


推荐阅读