FLAMEGPU/FLAMEGPU2

Agent Python MsgArray problems

Closed this issue · 1 comments

Discussed in #1109

Originally posted by LangLEvoI September 20, 2023
Hi there, I'm using Agent Python to build a simple model for more understanding of Flame GPU 2, based on the Circle tutorial.

An agent could randomly pick up another agent, replicating another one's status in my new model.

But some errors occurred when I tried to use MessageArray. Could I fix it somewhere?

First, the definition about 1D message array AND agent functions:

message = model.newMessageArray('variant')
message.setLength(5)
message.newVariableInt('var')


@pyflamegpu.agent_function
def output_message(message_in: pyflamegpu.MessageNone, message_out: pyflamegpu.MessageArray):
    message_out.setIndex(pyflamegpu.getID() - 1)
    message_out.setVariableInt("var", pyflamegpu.getVariableInt("var"))

    return pyflamegpu.ALIVE


@pyflamegpu.agent_function
def input_message(message_in: pyflamegpu.MessageArray, message_out: pyflamegpu.MessageNone):
    interlocutor = pyflamegpu.random.uniformInt(0, 4)
    msg = message_in.at(interlocutor - 1)

    pyflamegpu.setVariableInt("var", msg.getVariableInt('var'))

    return pyflamegpu.ALIVE

When I ran the programme, the first error:

---------------------------------------------------
--- JIT compile log for input_message_program ---
---------------------------------------------------
input_message_impl.cu(7): error: class "flamegpu::MessageArray3D::In::Message" has no member "getVariableInt"

1 error detected in the compilation of "input_message_program".
 
---------------------------------------------------
Traceback (most recent call last):
  File "/app/lilei/projects/flame/simple.py", line 115, in
    cuda_model.applyConfig()
  File "/app/lilei/miniconda3/envs/rapids/lib/python3.8/site-packages/pyflamegpu/pyflamegpu.py", line 7223, in applyConfig
    return _pyflamegpu.Simulation_applyConfig(self)
pyflamegpu.pyflamegpu.FLAMEGPURuntimeException: (InvalidAgentFunc) /__w/FLAMEGPU2/FLAMEGPU2/src/flamegpu/detail/JitifyCache.cu(380): Error compiling runtime agent function (or function condition) ('input_message'): function had compilation errors (see std::cout), in JitifyCache::buildProgram().

When I commented this line in input_message function and ran again:

# pyflamegpu.setVariableInt("var", msg.getVariableInt('var'))

A new error:

Traceback (most recent call last):
  File "/app/lilei/projects/flame/simple.py", line 117, in
    cuda_model.simulate()
  File "/app/lilei/miniconda3/envs/rapids/lib/python3.8/site-packages/pyflamegpu/pyflamegpu.py", line 7310, in simulate
    return _pyflamegpu.CUDASimulation_simulate(self, *args)
pyflamegpu.pyflamegpu.FLAMEGPURuntimeException: (DeviceError) Device function 'input_message' reported 2 errors.
First error:
flamegpu/runtime/messaging/MessageArray/MessageArrayDevice.cuh(564)[0,0,0][0,0,0]:
Index is out of bounds for Array messagelist (4294967295 >= 5).

The strange thing is that when I changed the random_seed from 12 to 112654 by accident, this error disappeared...

Another issue is about cuda_model.CUDAConfig().device. It didn't work when I set it to other device numbers, it always uses the default device.

cuda_model = pyflamegpu.CUDASimulation(model)

cuda_model.SimulationConfig().steps = 10
cuda_model.SimulationConfig().random_seed = 112654
cuda_model.CUDAConfig().device = 1

cuda_model.applyConfig()
cuda_model.simulate()

Thx a lot!

Need to check whether this can be reproduced, but it appears array messages may be being processed wrong.

With the codegen from current master

@pyflamegpu.agent_function
def input_message(message_in: pyflamegpu.MessageArray, message_out: pyflamegpu.MessageNone):
    interlocutor = pyflamegpu.random.uniformInt(0, 4)
    msg = message_in.at(interlocutor - 1)

    pyflamegpu.setVariableInt("var", msg.getVariableInt('var'))

    return pyflamegpu.ALIVE

Translates to

FLAMEGPU_AGENT_FUNCTION(input_message, flamegpu::MessageArray, flamegpu::MessageNone){
    auto interlocutor = FLAMEGPU->random.uniform<int>(0, 4);
    auto msg = FLAMEGPU->message_in.at((interlocutor - 1));
    FLAMEGPU->setVariable<int>("var", msg.getVariableInt("var"));
    return flamegpu::ALIVE;
}

Hence the incorrect msg.getVariableInt("var").

Obvious bug would be that it only expects message methods inside a message loop when transpiling. Will require some investigation, possibly input from @mondus.

The doc comment of codegen.py::dispatchMemberFunction() seems to confirm this has been overlooked, not immediately clear (to me) the best way to address it though. To do it properly would require some AST magic to track that msg was returns by message_in.at().

Lazy option would just be to regex groups replace all instances of getVariableType, but could break some esoteric cases.