使用Matlab parfor循环处理类

时间:2016-03-13 21:59:44

标签: matlab handle parfor

我咨询了#34; Handle Classes"

部分

http://uk.mathworks.com/help/distcomp/objects-and-handles-in-parfor-loops.html

并写下:

parfor j = 1:length(stores)
    store = stores(j);
    dataj = somefunction(store.someproperty, data(data.store == store.id, :));
    stores(j) = store.dosomething(dataj);
end

其中dosomething修改了store的状态。 (store是句柄类)。

循环适用于for;切换到parforstore对象的状态无法更新。

这是Matlab的文档问题,还是我对它的理解?

UPD。编辑评论很痛苦,所以我继续在这里。这是一个玩具类,有两种方法,修改对象的状态。

classdef shop < handle  
    properties  
        stock = 10
    end    
    methods
        function clearstock(obj)
           obj.stock = 0;
        end
        function[obj] = clearstock2(obj)
           obj.stock = 0;
        end
    end    
  end

现在测试脚本:

n = 1;
shops = repmat(shop, n, 1);
sprintf('Stock before: %d', shops(1).stock)
% A
parfor i = 1:n
    shops(i).clearstock;
end 
sprintf('Stock after: %d', shops(1).stock)
% B
shops = repmat(shop, n, 1);
parfor i = 1:n
    shops(i).clearstock2;
end 
sprintf('Stock after: %d', shops(1).stock)
% C
shops = repmat(shop, n, 1);
parfor i = 1:n
    shop = shops(i);
    shop.clearstock;
    shops(i) = shop;
end 
sprintf('Stock after: %d', shops(1).stock)
% D
shops = repmat(shop, n, 1);
parfor i = 1:n
    shop = shops(i);
    shop = shop.clearstock2;
    shops(i) = shop;
end 
sprintf('Stock after: %d', shops(1).stock)

(A,B)保持状态不变,(C,D)按预期/广告工作。现在,我的真实&#39;非玩具&#39;对象&#39; state是内置类和自定义类的混合。 (未更新的state元素是数值数组的单元格数组)。我想知道后者是后者吗?

UPD2。用户定义的句柄类作为属性 - 仍然按预期工作。

%MANAGER.M
classdef manager < handle
    properties
        name
        salary = 100000;
    end
    methods
        function[obj] = manager(name)
            obj.name = name;
        end
        function giveraise(obj)
            obj.salary = 200000;
        end
        function[obj] = giveraise2(obj)
            obj.salary = 300000;
        end
    end
end
%SHOP.M
classdef shop < handle
    properties
        stock = 10;
        manager = manager('John Doe');
    end    
    methods
        function clearstock(obj)
            obj.stock = 0;
        end
        function[obj] = clearstock2(obj)
            obj.stock = 0;
        end
    end
end
clc
n = 1;
shops = repmat(shop, n, 1);
sprintf('Stock before: %d', shops(1).stock)
sprintf('Salary before: %d', shops(1).manager.salary)
% A2
parfor i = 1:n
    shops(i).clearstock;
    shops(i).manager.giveraise;
end 
sprintf('Stock after: %d', shops(1).stock)
sprintf('Salary after: %d', shops(1).manager.salary)
% B2
shops = repmat(shop, n, 1);
parfor i = 1:n
    shop = shops(i);
    shop.clearstock;
    shop.manager.giveraise;
    shops(i) = shop;
end 
sprintf('Stock after: %d', shops(1).stock)
sprintf('Salary after: %d', shops(1).manager.salary)
% C2
shops = repmat(shop, n, 1);
parfor i = 1:n
    shop = shops(i);
    shop.manager = shop.manager.giveraise2;
    shop = shop.clearstock2;
    shops(i) = shop;
end 
sprintf('Stock after: %d', shops(1).stock)
sprintf('Salary after: %d', shops(1).manager.salary)

那是关于价值类的吗?

UPD3。不,shop属性的用户定义值类工作正常。我停下来,直到我能想出一个可重复的例子。

2 个答案:

答案 0 :(得分:1)

这有点棘手,因为我们没有看到整个代码,但我最好的猜测是dosomething方法返回修改后的store对象实例,并且而是返回别的东西。当您使用通常的for循环运行它时,此方法实际上更改了store句柄对象。但是,当您使用parfor运行它时,唯一在循环外持久保存的是dosomething的返回值,该值已分配给stores(j)。请尝试以下方式:

parfor j = 1:length(stores)
    store = stores(j);
    dataj = somefunction(store.someproperty, data(data.store == store.id, :));
    store.dosomething(dataj);
    stores(j) = store;
end

作为替代方案,请确保dosomething返回对象本身,即

function obj = dosomething(obj, dataj)
    % ...
end

答案 1 :(得分:0)

问题解决了,它位于所呈现的代码之外。

parfor循环位于函数simulateoneday内,该函数在循环中从函数simulatemultipledays调用。 simulatemultipledays会将simulateonedaystore对象传递给parfor,然后转到parfor

simulatemultipledays不是'重置'对象的状态 - 相反,它是simulateoneday - - - simulateoneday段。当我'simulatemultipledays吸收for时,事情开始发挥作用。

我想知道我是否已经通过引用传递了值传递,但是嘿,代码在parfor下工作得很好 - 它是 public class CategoryActivity extends BaseActivity implements View.OnClickListener { private RelativeLayout mReLayout; private byte[] mImageByte; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_1); addControl(); addEventOnClick(); mReLayout.setDrawingCacheEnabled(true); } private void addEventOnClick() { findViewById(R.id.layout_category_1).setOnClickListener(this); } private void addControl() { mReLayout = (RelativeLayout) findViewById(R.id.relative_category); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.layout_category_1: startActivity(); break; default: break; } } private void startActivity() { Bitmap layoutBitmap = Bitmap.createBitmap(mReLayout.getWidth(), mReLayout.getHeight(), Bitmap.Config.ARGB_4444); Canvas canvas = new Canvas(layoutBitmap); mReLayout.draw(canvas); ByteArrayOutputStream bStream = new ByteArrayOutputStream(); layoutBitmap.compress(Bitmap.CompressFormat.PNG, 90, bStream); mImageByte = bStream.toByteArray(); Intent mIntent = new Intent(Activity1.this, Activity2.class); mIntent.putExtra(Constant.BYTE_IMAGE, mImageByte); startActivity(mIntent); } } ,它破坏了东西