社区首页 >问答首页 >在MATLAB中的写拷贝和varargin

在MATLAB中的写拷贝和varargin
EN

Stack Overflow用户
提问于 2021-01-12 11:22:56
回答 3查看 302关注 0票数 3

MATLAB文档中有避免不必要的数据副本一节,其中可以找到以下语句:

抄写 如果函数不修改输入参数,MATLAB就不会复制输入变量中包含的值。

在这种情况下,没有关于varargin的任何消息。我试图找出一个能够监视内存使用情况的函数,但没有成功。所以我想问的是:复制写功能与varargin一起工作吗?

假设函数function Y = f(x,y,z)相对于函数function Y = f(varargin)。在第一种情况下,函数调用f(a,b,c)不会复制abc (不管变量的类型如何)。在第二种情况下,函数调用f(a,b,c)的行为并不清楚。MATLAB会指出varargin{1}avarargin{2}bvarargin{3}c而不显式创建单元数组,还是vararginabc的显式连接(因此内存将在单元数组中存储这三个变量的副本)?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-01-12 21:50:46

varargin是一个单元格数组。当您将对象放置到单元格数组中时,对象不会被真正复制,但它的引用计数会增加:

代码语言:javascript
代码运行次数:0
复制
a = [1 2 3];
b = 5;
c = {4, 6};
varargin = {a,b,c};

这里只增加了abc所指向的对象的引用计数。当你这样做时:

代码语言:javascript
代码运行次数:0
复制
varargin{1}(2) = 7;

因为它希望写入a指向的对象,所以它复制了该数组对象,并将新数组的第二个元素设置为7。新的数组放置在varargin的第一个单元格中,并且减少了a指向的对象的引用计数。然而,MATLAB jit编译器可能会进行更多的优化,并且它可能会就地创建变量,因此根本不会创建单元格数组。另一种可能的优化可能与标量这样的小对象有关。它们是廉价的对象,可以廉价复制,而且可能没有参考计数。

票数 5
EN

Stack Overflow用户

发布于 2021-01-14 17:44:29

这是一个涉及更多的问题,这似乎在一开始。部分原因是MATLAB文档中没有完整的文档,还有一部分是因为多年来幕后的共享机制发生了变化。首先,我将简要描述MATLAB变量是什么。然后我将描述MATLAB使用的各种共享机制。最后,我将描述这些共享机制是如何在MATLAB幕后使用的。

MATLAB变量:

MATLAB变量基本上是一个名为mxArray的C结构,它包含各种字段,用于保存大小、类、存储类和数据指针等信息。这个C结构的地址通常称为变量的“结构地址”,数据指针通常称为"Pr“、" Pi”、"Ir“、"Jc”等。对于MATLAB的后期版本,复杂的数据被交织在一起,没有Pi指针。对于内部数字、逻辑和char类,数据直接存在于Pr和Pi数据指针(以及用于稀疏变量索引的Ir和Jc指针)后面。对于OOP类mex类变量,在实际数据存在的数据指针背后有一种专有结构,用户无法直接访问该结构(限制OOP类mex变量在mex例程中的有用性的根本缺陷IMO )。

变量共享:

MATLAB以下列方式共享变量:

深拷贝:问题中的变量不是与任何其他变量共享任何内容。

共享数据副本:多个变量可以有不同的结构地址,但具有相同的数据指针。例如,这通常是直接的全变量赋值或完全变量的整形所产生的结果。过去,mxArray (CrossRef)中有一个字段,它是所有这些变量链接列表的一部分。稍后版本的MATLAB只有一个计数器来告诉您有多少变量是列表的一部分,但是列表本身不再是用户可以访问的。

引用副本:多个变量可以具有完全相同的结构地址。mxArray (refcount)中的字段指示有多少变量共享相同的结构地址。这是通常用于单元格或结构变量元素的内容。

父副本:它本身并不是一个副本,但是在嵌套的结构和单元格数组中,由于上游共享,变量最终可能与变量的其他部分或其他变量共享。在mxArray本身中没有这方面的迹象。也就是说,CrossRef和refcount看起来是不共享的,但是共享实际上正在发生。

句柄复制:如果OOP类then变量是从句柄派生出来的,那么多个变量基本上是共享的。在mxArray本身中不会出现这种情况,并且这些变量不遵循正常的“复制即写”或“延迟复制”规则。

什么时候使用共享?

这是它变得粘稠的地方。这些规则没有公布,而且这些年来发生了变化。我能做的就是举几个例子:

-共享数据副本示例

代码语言:javascript
代码运行次数:0
复制
A = B; % direct whole variable assignment (earlier versions of MATLAB)

A{1} = B; % assigning from workspace into cell or struct (earlier versions of MATLAB)

A = reshape(B,whatever); % reshape of full variable

B{1} % cell or struct element in expression or assignment

fun(B); % function arguments are passed as shared data copies of original

A = typecast(B,'whatever'); % later versions of MATLAB only. Early versions did deep copy.

-参考副本

代码语言:javascript
代码运行次数:0
复制
A = B; % direct whole variable assignment (later versions of MATLAB)

A{1} = B{1}; % assignment among cell or struct elements

A = 1:5; % literal assignment of small variable can result in background reference copy

-家长副本示例

代码语言:javascript
代码运行次数:0
复制
A.x = 5; B = A; % A.x is sharing with B.x through the parent A and B sharing.

原来的问题是:

非Mex函数参数通过某种类型的复制机制传递到函数中。无论是文字变量还是varargin,通常都使用共享数据副本(无论是显式参数还是构建varargin单元数组的结果)。我看到的唯一例外是,有时嵌套函数可以传递一个标量变量的深度副本,而不是共享的数据副本。因此,“写上复制”或“延迟复制”机制既适用于函数内部的文字参数,也适用于varargin参数,因为在这两种情况下,您实际上都在处理函数中原始数据的共享数据副本(或者在稍后版本的MATLAB中可能是引用副本)。要注意的是,如果在函数调用中使用特殊的语法,则可以让MATLAB解析器认识到您正在尝试修改变量“就地”,并避免深拷贝,否则就会发生。

Mex函数参数略有不同。旧版本的MATLAB总是用于传递原始的可变结构地址,但较晚版本的MATLAB使用与非Mex函数相同的规则并传递共享数据副本(尽管标量可能作为深度副本传递)。

因此,函数中的“复制即写”或“延迟复制”机制实际上并没有什么特别之处。传入原始变量的共享数据副本或引用副本。因此,如果不对其进行任何更改,则函数内部将不会进行深度复制。如果您确实更改了参数变量的元素,那么将首先进行深度复制(即未共享)。但这是在MATLAB的任何级别上发生的行为.如果您更改了共享变量的元素,则必须首先进行深度复制。无论你是否在一个函数中,应用的规则都是相同的.如果该变量是共享的,并且您更改了一个元素,那么将首先进行深度复制。

票数 8
EN

Stack Overflow用户

发布于 2021-01-13 07:44:49

作为@rahnema1 1,MATLAB的复制写机制(也称为延迟复制)适用于每个副本,而不仅仅是函数参数。

演示这一点的一种方法是使用从Yair的无文件的MATLAB博客修改的以下MEX文件

代码语言:javascript
代码运行次数:0
复制
#include "mex.h"
#include <cstdint>
void mexFunction( int /*nlhs*/, mxArray* plhs[], int nrhs, mxArray const* prhs[]) {
   if (nrhs < 1) mexErrMsgTxt("One input required.");
   plhs[0] = mxCreateNumericMatrix(1, 1, mxUINT64_CLASS, mxREAL);
   std::uint64_t* out = static_cast<std::uint64_t*>(mxGetData(plhs[0]));
   out[0] = reinterpret_cast<std::uint64_t>(mxGetData(prhs[0]));
}

您可以将其保存为getaddr.cpp并使用mex getaddr.cpp进行编译。现在您有了一个函数,它显示存储数组数据的地址。

例如,如果我们复制一个数组,该副本将具有相同的数据地址。然后,当我们写信到副本时,它的数据地址将改变:

代码语言:javascript
代码运行次数:0
复制
>> a=zeros(5);
>> getaddr(a)
ans =
  uint64
   105553130112928
>> a(1)=1;
>> getaddr(a)
ans =
  uint64
   105553130112928
>> b=a;
>> getaddr(b)
ans =
  uint64
   105553130112928
>> b(1)=4;
>> getaddr(b)
ans =
  uint64
   105553130078944

单元格数组也是如此,这与问题直接相关,因为输入参数是在单元格数组varargin中收集的。

代码语言:javascript
代码运行次数:0
复制
>> a=zeros(5);
>> b=zeros(8);
>> v={a,b};
>> getaddr(a)
ans =
  uint64
   105553130246144
>> getaddr(v{1})
ans =
  uint64
   105553130246144

请注意,单元格数组只不过是一个数组,其数据类型为“数组”,因此可以包含任何类型的数组作为其元素。基本上,它是指向其他数组的指针数组。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65690681

复制
相关文章
matlab vargin_matlab varargin
那么在这个函数里,varargin就是一个cell数组,它包含了用户输入的参数。下面是一个例子:
全栈程序员站长
2022/11/16
9240
matlab在axis,matlab中axis的用法
>> axis([0 2*pi -0.9 0.9]) 图 5.1.3 使用了图形修饰的 plot 函数绘制的正弦曲线 5.1.3 图形的比较显示 在一般默认的情况下,MATLAB 每次使用 plot ……
全栈程序员站长
2022/09/06
1.9K0
java浅拷贝和深拷贝的区别_js中深拷贝和浅拷贝的区别
浅拷贝:对基本类型的数据是值拷贝,对String类型的拷贝也可以看作是值拷贝,这里不做讨论;
全栈程序员站长
2022/11/15
8890
java浅拷贝和深拷贝的区别_js中深拷贝和浅拷贝的区别
c浅拷贝和深拷贝的区别_js中深拷贝和浅拷贝的区别
先考虑一种情况,对一个已知对象进行拷贝,编译系统会自动调用一种构造函数——拷贝构造函数,如果用户未定义拷贝构造函数,则会调用默认拷贝构造函数。
全栈程序员站长
2022/09/27
7240
c浅拷贝和深拷贝的区别_js中深拷贝和浅拷贝的区别
JS中数组的深拷贝和浅拷贝
变量保存的是一个指针,存放在栈内存中,指针指向一个位置,这个位置就是存放在堆内存引用类型的值
杨肆月
2019/08/15
2.4K0
JS中数组的深拷贝和浅拷贝
Python 中浅拷贝和深拷贝的区别
CVPR 2021 相关论文、代码 、解读和demo整理,同时为了方便下载论文,已把部分论文上传到上面了,欢迎小伙伴们 star 支持一波!
AI算法与图像处理
2021/04/21
9770
Python 中浅拷贝和深拷贝的区别
python中浅拷贝和深拷贝
由结果看,PHP中array_push方法和array_object的结果也不同。
老高的技术博客
2022/12/27
4080
JavaScript中浅拷贝和深拷贝的区别和实现
要理解 JavaScript中浅拷贝和深拷贝的区别,首先要明白JavaScript的数据类型。JavaScript有两种数据类型,基础数据类型和引用数据类型。
Javanx
2019/09/05
6400
JavaScript中浅拷贝和深拷贝的区别和实现
JavaScript中浅拷贝和深拷贝的区别和实现
要理解 JavaScript中浅拷贝和深拷贝的区别,首先要明白JavaScript的数据类型
tianyawhl
2019/04/04
5350
JavaScript中浅拷贝和深拷贝的区别和实现
深拷贝与浅拷贝以及写时拷贝
假设B复制了A,当修改A时,看B是否会发生变化。如果B也跟着变了,说明这是浅拷贝;如果B没变,那就是深拷贝。
Jasonangel
2021/05/28
6640
C++中的深拷贝和浅拷贝介绍
对于基本类型的数据以及简单的对象,它们之间的拷贝非常简单,就是按位复制内存。例如:
芯动大师
2023/09/18
4610
C++中的深拷贝和浅拷贝介绍
matlab如何使用循环语句_matlab中循环语句怎么写
clc clear a=1; m=3; for i=1:m %理解此处的m不是向量,是循环时的某一个固定值 b(i)=a*i %得到的b值保留前一个循环中计算的值。是一个随着i变化的向量,loop1时向量中有1个元素;loop2时有2个元素,分别是loop1中值和loop2中的值。这种情况下,不会覆盖loop1中参数。 c=a*i %得到循环某个值的具体值。是一个元素,loop2会覆盖loop1中元素 d(3)=a*i %d(3)表示其中包含3个元素,若不够则用0填。固定为一个有3个元素的向量,元素不够是用0填,会覆盖loop1中元素。 end
全栈程序员站长
2022/09/27
6.2K0
浅谈JS中对象的深拷贝和浅拷贝
浅拷贝和深拷贝的'深浅'主要针对的是对象的‘深度’,常见的对象都是'浅'的,也就是对象里的属性就是单个的属性,而'深'的对象是指一个对象的属性是另一个对象,也就是对象里面嵌套对象,就像嵌套函数一样。 为什么要使用深拷贝和浅拷贝呢? 如果现有var obj1 = {...}这个对象,想要复制对象obj1,一贯的做法就是obj2 = obj1,这时虽然obj2拥有了obj1的所有属性,但obj2却不是自由的,因为它的改动会影响到obj1,obj1的改动也会影响到obj2,这不是我们所希望的,所以要用到深拷贝和浅
小胖
2018/06/27
6.8K2
在MATLAB中RSA加密
[Modulus, PublicExponent, PrivateExponent] = GenerateKeyPair;
万木逢春
2019/05/10
1.8K0
并发容器之写时拷贝的 List 和 Set
对于一个对象来说,我们为了保证它的并发性,通常会选择使用声明式加锁方式交由我们的 Java 虚拟机来完成自动的加锁和释放锁的操作,例如我们的 synchronized。也会选择使用显式锁机制来主动的控
Single
2018/01/04
7360
并发容器之写时拷贝的 List 和 Set
Objective-C中的深拷贝和浅拷贝
        在Objective-C中对象之间的拷贝分为浅拷贝和深拷贝。说白了,对非容器类的浅拷贝就是拷贝对象的地址,对象里面存的内容仍然是一份,没有新的内存被分配。对非容器类的深拷贝就是重写分配一块内存,然后把另一个对象的内容原封不动的给我拿过来。对容器类的深拷贝是对容器中的每个元素都进行拷贝,容器类的浅拷贝是对容器里的内容不进行拷贝,两个容器的地址是不同的,但容器里的所装的东西是一样的,在一个容器中修改值,则另一个浅拷贝的容器中的值也会变化。所以对非容器类看对象是否为深拷贝还是浅拷贝就得看对象的内存
lizelu
2018/01/11
1.1K0
Python中浅拷贝和深拷贝的区别总结与
单层浅拷贝 import copy a = 1 # 不可变数据类型 copy_a = copy.copy(a) print(id(a),id(copy_a)) # 内存地址相同 a = [1,2] # 可变数据类型 copy_a = copy.copy(a) print(id(a),id(copy_a)) # 内存地址不相同 单层深拷贝 import copy a = 1 # 不可变数据类型 copy_a = copy.deepcopy(a) print(id(a),id(copy_a)) #
py3study
2020/01/21
5120
这6个命令助你玩转matlab自定义函数
函数对于matlab的重要性这里就不在赘述了(你了解matlab局部函数吗?)。matlab自带的函数虽包罗万象、但并不可能揽括一切,在实际编程过程中往往还需要编程者根据实际问题编写适合解决当下问题的函数,这也就是所谓的自定义函数。
巴山学长
2019/11/01
7930
PHP中引用的详解(引用计数、写时拷贝)
PHP中引用意味着用不同的名字访问同一个变量内容,引用不是C的指针(C语言中的指针里面存储的是变量的内容,在内存中存放的地址),是变量的另外一个别名或者映射。注意在 PHP 中,变量名和变量内容是不一样的,因此同样的内容可以有不同的名字。 最接近的比喻是 Unix 的文件名和文件本身――变量名是目录条目,而变量内容则是文件本身。引用可以被看作是 Unix 文件系统中的紧密连接或者wins的快捷方式。
黄规速
2022/04/14
3.7K0
点击加载更多

相似问题

varargin在matlab中的应用

12

利用varargin的MATLAB fminsearch

13

MATLAB中的Varargin不适合我

17

PHP在写数组和对象上的拷贝

113

将varargin和nargin从Matlab转换为Python

11
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档