From: "Simon Kröger" Date: 2007-03-16T07:35:06+09:00 Subject: Re: [QUIZ] SimFrost (#117) Hi again Jupp, i don't want to start a flamewar here, trust me. I admit that C is faster than ruby in all situations that might matter (except developing speed). Nevertheless some comments to your code: > def output_state(state, tick) this is where half the time is spend - at least on my system > home > puts "Simulation tick #{tick}" > filename = "tick_#{'%05d' % tick}.pgm" > File.open(filename, 'w') do |file| > file.puts <<-EOF > P2 > # #{filename} > #{state.first.length} #{state.length} > 2 > EOF > state.each do |row| > row.each do |elem| > file.puts elem.to_s > end > end replacing this with file.puts( state.map do |row| row.join("\n") end.join("\n") ) dramatically cuts down the time spend in IO. A simple file.puts state does not. Which might give a hint on why this is so slow, puts is recursively called for every element in the array while join is only called once for each row. > end > end > > ##################################################################### > # see if state is frozen out (i.e. no more vapor is present) > ##################################################################### > > class Array > def frozen_out? > not self.flatten.member?(1) > end > end You create large new arrays here every tick. To be fair replace it with def frozen_out? not any? {|row| row.member?(1)} end > ##################################################################### > # the simulation itself > ##################################################################### > > settings = get_settings > cols = settings["cols"], > rows = settings["rows"], > prob = settings["prob"] > state = initial_state(cols, rows, prob) > tick = 0 > cls > while true > output_state(state, tick) > break if state.frozen_out? > tick += 1 > offset = (tick + 1) % 2 > i = offset > while i < rows > i1 = (i + 1) % rows > j = offset > while j < cols > j1 = (j + 1) % cols > if [ state[i][j], > state[i][j1], > state[i1][j], > state[i1][j1] ].member?(2) this creates new arrays in the innermost loop.... better do a simple if (state[i][j] == 2 || state[i][j1] == 2 || state[i1][j] == 2 || state[i1][j1] == 2) if you care for speed (you do that in C) > state[i][j] = 2 if state[i][j] == 1 > state[i][j1] = 2 if state[i][j1] == 1 > state[i1][j] = 2 if state[i1][j] == 1 > state[i1][j1] = 2 if state[i1][j1] == 1 > else > if rand < 0.5 > state[i][j], state[i][j1], state[i1][j], state[i1][j1] = > state[i][j1], state[i1][j1], state[i][j], state[i1][j] > else > state[i][j], state[i][j1], state[i1][j], state[i1][j1] = > state[i1][j], state[i][j], state[i1][j1], state[i][j1] > end > end parallel assignments do create arrays also. do the same as in C: else h00 = state[i][j]; h01 = state[i][j1]; h10 = state[i1][j]; h11 = state[i1][j1]; if (rand < 0.5) state[i][j] = h01; state[i][j1] = h11; state[i1][j] = h00; state[i1][j1] = h10; else state[i][j] = h10; state[i][j1] = h00; state[i1][j] = h11; state[i1][j1] = h01; end end > j += 2 > end > i += 2 > end > end > > [...] Well that's it. At least my ruby version doubled its speed. (but i only tested for small simulations, would you run these modifications to see the difference on your system with your data?) > Josef 'Jupp' Schugt cheers Simon