0

I'm trying to use ray module to on an existing code based on if an env variable is true or not. This is what I've done so far. this code structure is similar to mine but not exactly due to it's size.

import os

if os.getenv("PARALLEL"):
    import ray
    ray.init()

class A(object):
    def __init__(self, attr):
          self.attr = attr 

    def may_be_remote(func):
          return ray.remote(func) if os.getenv("PARALLEL") else func

    @may_be_remote
    def do_work(self):
          #work code

    def execute(self, n):
           for _ in range(n):
                do_work.remote()

Then, I call the execute function of class A :

a = A()
a.execute(7)

I get AttributeError : 'function' has no attribute 'remote' on that line.

Where did I go wrong with this code please?

AnotherBrick
  • 153
  • 3
  • 6
  • 14
  • It looks like you're calling `.remote` twice. If `execute` just called `self.do_work()` this should work – Alex Jun 04 '20 at 00:59

2 Answers2

0

You are accessing remote() on the function do_work, which is not defined.

Did you mean to just call do_work()?

vishnufka
  • 134
  • 2
  • 8
0

Unfortunately ray makes it hard to get transparent code to switch easily as you intend. Following https://docs.ray.io/en/latest/ray-overview/index.html#parallelizing-python-classes-with-ray-actors the quite strange insert-.remote syntax is like...

import os
use_ray = os.getenv("PARALLEL") is not None
if use_ray:
    import ray
    ray.init()

def maybe_remote(cls):
    return ray.remote(cls) if use_ray else cls

@maybe_remote
class A:
    def __init__(self, attr):
        self.attr = attr

    def do_work(self, foo):  # do something
        self.attr += foo

    def get_attr(self):  # return value maybe from remote worker
        return self.attr

if __name__ == '__main__':
    n = 7
    if use_ray:
        a = A.remote(0)
        for i in range(1, n + 1):
            a.do_work.remote(i)
        result = ray.get(a.get_attr.remote())
    else:
        a = A(0)
        for i in range(1, n + 1):
            a.do_work(i)
        result = a.get_attr()

    expect = int((n / 2) * (n + 1))
    assert expect == result

Not sure there is also an easy (decorator) solution for the differences in the method calls.

thoku
  • 1,120
  • 9
  • 27