Running functions in parallel


Andreschrosa

Recommended Posts

We have several equipments connected in ethernet-RS485 conversors, and the network has about 9 of those conversors. I'm wrinting a sequence to read the memories of several equipments, and I wanted that reading to be run in parallel.

The sequence that reads their memories is ready, but my doubt is in the next step:

using the function notation on a sequence, can it be called over several times to run in parallel or it would aways run to the end of each function call before starting the next function call in the for loop?

I will post bellow an algorithm of what I'm doing:

for each conversor in the network do
  for each equipment in a conversor do
	ReadEquipmentMemory(conversor, equipment)
  endfor
endfor

ReadEquipmentMemory is the function sequence I wanted to run in parallel.

Link to comment
Share on other sites

You can't start a sequence like ReadEquipmentMemory that has parameters on its own. The loop algorithm you showed won't work because it will run everything sequentially. What you need to do is create a sequence for each piece of equipment that calls readequipmentmemory with different parameters, then start all those sequences. "Those" sequences would only have one line, namely the ReadEquipmentMemory() function call.

If you don't know how much equipment you are going to have ahead of time, there is a more advanced way of doing this.

Link to comment
Share on other sites

Use the startthread() function to start a thread for each of the loops:

startthread(function, threadname, priority)

function is the function (as a string)

threadname is the name of the thread (so you can stop it later)

priority is a number from 0 to 5, just like sequence priorities

so:

startthread("ReadEquipmentMemory(1,2)","rem12",3)

Each thread must have a unique name, and make sure you keep track of your thread names in a variable or similar so you can stop the threads. Stopping them is just:

stopthread(threadname)

You can also get the thread status by doing:

getThreadStatus(threadname)

which returns a string describing what the thread is doing. Handy for debugging.

I call this advanced because there is no GUI to start/stop threads or even tell what threads are running. You are responsible for the threads. DAQFactory will at least stop all the threads when the document is closed, but that's about it. Its also harder to debug. Breakpoints don't apply to script running in a user thread started with these functions, so you'll want to test your script using regular sequences first.

Link to comment
Share on other sites

It seens to work, although the data seens to be shuffled when inserted in the database.

My memory reading function call another function sequence that calls another function sequence and so on, there is a total of 5 function sequences called from the initial one.

Maybe I should start a thread for each one of those, opposed to let then just call functions?

Link to comment
Share on other sites

You should only have one thread for each device, otherwise things will really get complicated and likely will run slower. The connection to the device is the bottleneck so it doesn't make sense to use more than one thread per connection. I'm not sure what you mean by shuffled data, maybe you can clarify.

Link to comment
Share on other sites

Probably this is the problem then: we currently have three to four equipments per device.

By shuffled data I meant some data from one equipment was sent to the database as belonging to another, likewise caused by the five threads running on the same device.

Think it will have to run sequentialy inside each device in the network, each device on it's thread then.

Link to comment
Share on other sites

I was thinking to use another application to read those memories, but my main doubt is can the same IP (the ethernet-RS485 conversor IP) be used by DAQFactory to send modbus read input float and send another modbus command to read the memory? Does DAQFactory locks the TCP/IP communication?

In the sequence I wrote to read the memory, I must do device.lockport() to get all memory blocks right, so I fear I might already have answered my own question.

Link to comment
Share on other sites

lockport() only locks the port within DAQFactory and then only with other code that uses lockport(). Our Modbus does lockport() internally, so you don't have to do it.

Whether another application can communicate with your converter at the same time as DF really depends on the hardware: whether is supports multiple clients. My guess is not. You are also going to have a hell of a time syncronizing two applications communicating with a serial to ethernet converter. I strongly recommend against it.

You should create one thread for each remote TCP device. Everything on that device should be within that thread. If you are swapping data, then you probably just have a scripting error somewhere, or a logic error. If you are using our Modbus protocol driver, the port remains locked during the entire frame, so data won't get swapped do to threading provided you are only using our Modbus driver.

Link to comment
Share on other sites

Yes, I'm using DAQFactory modbus for the read input float that keeps reading data from the equipments.

However there are times when the user will want to read the data stored in memory, I wanted to have it done in parallel with the data acquisition paused for about 3 hours, but it seens this will not work this way.

It would require for that other application to steal the connection from the converter, get the data from memory then get out and let DAQFactory continue to do the regular data acquisition. And that probably is prone to a lot more of errors and headache than it's useful to have implemented.

Instead, I'll advise the user to only read the data stored in memory in case of a particular event, one where he knows the communication with the DAQFactory application was cut and he need to see the memory.

Link to comment
Share on other sites

I can, but the problem is the time it takes to read all the memory while it still is registering (hardware restriction). It will take the all equipments in a single conversor down for about 2:28 for each equipment on a conversor.

The best solution in this case is like I said just read from memory in case of a big event that takes the machine running DAQFactory down. Anyway we got all the same values that go to memory being read by DAQFactory on the same 30 seconds interval, so it would be redundant data.

Thanks for the help =)

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.