Handle classes with Matlab parfor loops [closed]

我是研究僧i 提交于 2019-12-08 13:41:47

问题


I consult "Handle Classes" section of

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

and write this:

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

where dosomething modifies store's state. (store is a handle class).

The loop works fine with for; switch to parfor, and store object's state fails to be updated.

Is this a problem with Matlab's doc, or with my understanding of it?

UPD. Editing comments is a pain, so I continue here. Here's a toy class, with two methods, modifying the object's state.

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

Now the test script:

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) leave the state unchanged, (C,D) work as intended/advertised. Now, my 'real', 'non-toy' objects' state is a mix of built-in and custom classes. (The state element that is not being updated is a cell array of numeric arrays). Are the latter to blame, I wonder?

UPD2. A user-defined handle class as a property - still working as expected.

%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)

Is it about value classes, then?

UPD3. No, a user-defined value class for shop property worked fine. I stop until I can come up with a reproducible example.


回答1:


It's a bit tricky since we don't see the whole code, but my best guess is that dosomething method does not return the modified store object instance, and returns something else instead. When you run it with the usual for loop, this method actually changes store handle object. When you run it with parfor, however, the only thing that gets persisted outside the loop is the return value of dosomething that is assigned to stores(j). Please try the following instead:

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

As an alternative, make sure dosomething returns the object itself, i.e.

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



回答2:


Problem solved, and it lay outside of the presented code.

The parfor loop was inside a function, simulateoneday, which was called, in a loop, from function simulatemultipledays. simulatemultipledays would pass to simulateoneday an array of store objects, which would then go to parfor.

It wasn't parfor that was 'resetting' objects' state - instead, it was the simulatemultipledays-to-simulateoneday passage. When I 'absorbed' simulateoneday into simulatemultipledays, things started working.

I wondered if I had tripped up on pass-by-value-vs.-pass-by-reference, but hey, the code worked fine with for - it was parfor which broke things.



来源:https://stackoverflow.com/questions/35976395/handle-classes-with-matlab-parfor-loops

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!