Optimizing OSC - aka Synchronizing multiple screens

Hey OSC-using-folks,

I’m using OpenSoundControl for a networked video installation. The seven computers need to be synchronized and I’ve created a client and a server class (based on the OSC examples) to enable communication between the screens. Basically, when each client starts up, they send a handshake to the server, which then sends a message to each of the clients to draw a frame. When a frame is completed, the clients send a message to the server that a frame has been drawn. When the server received that notice from all the clients, it tells the clients to draw the next frame … and so on.

The setup is working fine … just rather slowly (12 fps instead of 30 fps) and I’m wondering what I might be able to do in order to speed things up. I’m using a gigabit ethernet switch and have disabled the airport cards on all of the MacMinis. Are there are optimizations from an OSC perspective or on OSX that might make this setup run faster? I imagine that it’s better to shorted the length of the strings that I’m sending across, but they’re usually only 5 characters.

Thanks for any advice,

Jeremy

PS - The server setup is based on Dan Shiffman’s MPE library for processing (http://www.mostpixelsever.com/). I’m planning to share the code real soon.

1 Like

Hey Jeremy

I am actually doing something similar at the moment. Making a quick and dirty version of MPE using ofNetwork - taking the same approach you are doing.

In my system the clients send a frame number message - when the server receives the same frame number from all the clients it sends a go signal to all the clients to draw the frame.

Performance is pretty bad in my system - aprox 12-15 fps but I am sure there is a lot I can do to speed it up. I figured udp would be a big improvement to start off with.

Anyway I will post my code later today and maybe we can get some input from the rest of the community on the best approach to this problem.

cheers theo

I don’t know if osc is using tcp or udp, but there is mad overhead with tcp in terms of multiple clients, at least w/ what I’ve seen. udp is quicker, less overhead by far.

best appraoch in my book for multiple client rendering is one server shipping udp packets of binary data (you can just create a struct and memcpy into a char array) preferably over multicast and client machines reading in a non blocking way… packets might want to contain a frame counter, so that you can tell if they got lost packets, etc. also crucial is that client machines read as fast as possible the data or otherwise you’ll get latency.

since multiple folks are working on this (and I have to too for a project in late april) I will try to code something when I’m back in the states.

take care!!
zach

OSC uses udp - so it should be faster. I’ll switch my code over to udp and see what the difference is.

The approach I am using doesn’t actually require sending any animation data - it just runs the same code on the different machines with a screen offset. To make sure all the animation starts with the same parameters I seed random with the same number.

I imagine this technique doesn’t work so well with interactive systems - where each screen needs to be updated with what happened on the other screen.

Anyway you can see it running here:
http://www.vimeo.com/794087

I am sure it can be crazy optimized :smiley:

I’m pretty sure OSC is UDP…perhaps you can use it with TCP but it’s likely to be UDP by default. UDP is lossy and fast, which is why it’s used exclusively in video streaming. It’s lossy because there is no confirmation that a packet has been received (unlike TCP)…and sometimes packets get lost in the network. So if you block waiting for a UDP packet you definitely want a timeout in case the packet doesn’t arrive.

I don’t think you need to speed up OSC, it should be pretty fast. 12 fps means a frame time of around 83 ms…I’m sure OSC transmission is a lot faster than that. However perhaps you can send a single byte instead of 5 chars (which is at least 5 bytes). Have a look at your synchronisation routine and try and speed that up perhaps…basically anywhere in the code where you are waiting for something to happen. Also, try a profiling tool. Not sure what’s best on OSX but if you use one it should tell you exactly which bit of code is taking up the most time.

OSC is USD

but it might give you just a bit too much overhead for what you want to do…

toxi over in london has re-implemented the MPE library (fro processing) using UDP and made it to work properly.

You should look into working with straight UDP packet, it would me much faster

m

hey guys. thanks for your answers. my next test was actually what zach was recommending, to setup the client machines to read as fast as possible … and allow the server to set the frame rate. i’m going to give that a shot this afternoon and report back.

there’s probably some more overhead in the fact that the server has to create the packet 7x before sending it out. i’m going to dig a little deeper into the osc code and see if there’s some kind of broadcast functionality that might speed things up. hopefully there will be more to report on later.

i’ll also try shortening the size of the packets that i’m sending.

theo, why’d you opt for using ofNetwork instead of OSC?

jeremy

dont create 7 packets! let UDP do the work for you

send the messages once to the whole network using a broadcast address
so if your machines are in the, say, 192.168.1.x network send a single packet at a time to 192.168.1.255 and it will be broadcasted to the whole subnet

Yeah multicast would be the way to go if you are using UDP.

The server would then send out the “draw frame” message to all the clients with one send command.

  
theo, why'd you opt for using ofNetwork instead of OSC?   
  

Well I am not too familiar with the osc protocol and for me it was just as easy to do it with ofNetwork (plus it is a good way to test the code).

I halted moving my code over to UDP for the time being as I don’t think a Most Pixels Ever model is ideal for what I need to do. I am setting up a multi projector installation where each projection surface is interactive and therefore affects all the other projections as well.

The approaches I am considering are:
a) Zach’s approach - A server does all the tracking and computation and then sends structs that contain vertices, color etc to each client. This could end up being a lot of data.

b) A sort of hybrid between zach’s approach and MPE where each client starts with the same conditions and then the server sends only the data that causes things to change. So if there are no people in front of the projections all the server has to send is a ‘render frame’ command.

I like the idea of the second approach but it is just theoretical at the moment - I have seen zach’s approach work well so I know it works.

I would love to hear people’s suggestions
Theo

Hi

don’t know exactly your installation, but for what i read the idea is to synchronize something that every client knows, the server doesnt have to send the data, only some kind of sync.

in that case, perhaps one of the problems is not the size of the packets but that every client sends a packet simultaneously so the switch has to serialize them introducing more delay (if you have a hub instead of a switch is worst because that packets will be lost and resent when using tcp). perhaps a solution can be that the server or one of the clients broadcast a sync packet with the frame number once every 10 frames for example. If one of the clients has got out of sync, it just re-syncs to that frame number but no client answers so there are no packet collision in the net.

of course use udp, tcp has longer headers and it implements some algorithms that implies answer for every packet sent.

also if the packets are very long you can try adjusting the udp packet size at operating system level so it adjusts to yout packet size, so only one udp header is sent for every application layer packet.

oh, and most operating systems, has some kind of ‘hey i’m here’ protocols so they automatically send something through the net, try to deactivate every other protocols, specially windows sharing and bonjour.

mbanzi,

that sounds pretty simple to setup, i just need to create an OSCSender object that’s initilized like this: sender.setup(“192.168.0.255”, 12350).

but the clients on 192.168.0.x don’t receiving anything. is it wrong to be using the 192.168.0 network (as opposed to 192.168.1)?

thanks,

jeremy

It doesnt make a difference but…
You should tell us which platform are u on and if you are on windows check the firewall, a lot of network problems end up being caused by it.

from my processing code :
oscP5 = new OscP5(this,12345);
myRemoteLocation = new NetAddress(“192.168.1.255”,12345);
OscMessage myMessage = new OscMessage("/play");
oscP5.send(myMessage, myRemoteLocation);

massimo

well, i’m running osx … with firewalls disabled in the system preferences. i’ll poke around a little bit more …

hey massimo,

ok, i just tested the oscReceive and oscSend demos using direct addressing of the client (192.168.0.1) and broadcasting to the subnet (192.168.0.255) … and broadcasting didn’t work. is anybody else able to cornfirm this?

jeremy

don’t know exactly your installation, but for what i read the idea is to synchronize something that every client knows, the server doesnt have to send the data, only some kind of sync.

this really depends on what is being rendered across the screens - for example, if it’s video, you could just send the name of the video and the playhead position. but for simulations – ie, spring systems, bouncing balls, etc – you will need either a master that knows everything (and sends draw information in a vector format) or some way (as theo describes) of clients handing off to each other. I’ve done both before – with noodles that travel from display to display – for example here and here:

http://www.aec.at/en/futurelab/projects-…-ctID=12805
http://www.youtube.com/watch?v=-JylIVD7phc

with the building, we had one master sending data of where the noodles are to 22 clients. With the tables we had smarter clients, that sent a signal when a noodle was leaving one table and heading to another.

I personally feel although it’s a bit harder, developing the first style (smart master, dumb clients) is preferable to smarter clients since I think it leads more directly to seamless interaction. With dumb clients, it’s easy to develop the software that runs the same on all machines and each machine is just a new viewport / clipper on the same material. it takes some work to setup at first, but it’s super flexible.

take care!
zach

ok, i just tested the oscReceive and oscSend demos using direct addressing of the client (192.168.0.1) and broadcasting to the subnet (192.168.0.255) … and broadcasting didn’t work. is anybody else able to cornfirm this?

Yes, it seems oscpack doesn’t allow broadcasting. When you open a socket you have to set a special option to allow broadcasting through it, and it’s not set in oscpack.

I’ve tried modifying the library and adding this line after the connect statement, and it works

setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &optval ,sizeof(optval));

the problem is that the socket is private inside oscpack and it has no accesors so any option can be changed to the socket without modifying the library.

arturo,

setting the address to 192.168.0.0/24 works for me on my own machine using the oscSend and oscReceive demos. i’ll test it out on the multiple-computer setup on tuesday. thanks so much for pointing out what i need to alter in the code!

jeremy

Hi jeremy

I deleted that message, because it doesn’t work. At first I thought it was working, but it only works in local, in fact anything you use as address that isn’t a real addres will work in local. I’ve sniffed the network connection and it is sending nothing with that address. When changing osc then it works.

[quote author=“mantissa”]hey massimo,

ok, i just tested the oscReceive and oscSend demos using direct addressing of the client (192.168.0.1) and broadcasting to the subnet (192.168.0.255) … and broadcasting didn’t work. is anybody else able to cornfirm this?

jeremy[/quote]

hey! i’m damian and i wrote the OSC addon :slight_smile:

broadcast should work. in my experience different router configurations handle broadcast differently. try 192.168.255.255 (or even 192.255.255.255?)

good luck and if you need any more help email me damian atat frey dotdot co dotdot nz

Hi Damian

Are you on windows? I don’t know under windows but with poxis sockets you have to set that option both in the sender and the receiver. The problem is not in your addon but in oscpack.

The broadcast address is always a bit complement between the ip and the netmask, so if you have

192.168.0.x as ip, 255.255.255.0 as netmask, your broadcast adress will be 192.168.0.255

172.16.x.x and 255.255.0.0 = 172.16.255.255