|
@@ -7,7 +7,8 @@ import time
|
7
|
7
|
import datetime
|
8
|
8
|
import numpy as np
|
9
|
9
|
from random import randint
|
10
|
|
-from multiprocessing import Pool, Process, Queue
|
|
10
|
+import multiprocessing
|
|
11
|
+from multiprocessing import Pool, Process, Pipe
|
11
|
12
|
|
12
|
13
|
logging.basicConfig(level=logging.INFO,
|
13
|
14
|
format="%(created)d %(asctime)s:%(module)s(%(lineno)d):%(levelname)s:%(message)s")
|
|
@@ -91,6 +92,8 @@ parser_gen.add_argument('--output-dir', '-A', type=str, default=None,
|
91
|
92
|
help="Save images for animation in this directory")
|
92
|
93
|
parser_gen.add_argument('--anim-div', '-D', type=int, default=2,
|
93
|
94
|
help='Save all X images (default 2) when -O given')
|
|
95
|
+parser_gen.add_argument('--anim-fmt', '-F', type=str, default='GTE_ANIM_%d.png',
|
|
96
|
+ help='Save all X images (default "GTE_ANIM_%d.png") when -O given')
|
94
|
97
|
parser_gen.add_argument('--world-height', '-y', type=int, metavar='HEIGHT',
|
95
|
98
|
default=512)
|
96
|
99
|
parser_gen.add_argument('--world-width', '-x', type=int, metavar='WIDTH',
|
|
@@ -104,7 +107,8 @@ parser_gen.add_argument('--gray', '-G', action='store_const',
|
104
|
107
|
parser_gen.add_argument('--no-diagonals', '-d', action='store_const',
|
105
|
108
|
default=False, const=True)
|
106
|
109
|
parser_gen.add_argument('--threads', '-t', type=int, metavar='N',
|
107
|
|
- default=2, help="Animation writting threads")
|
|
110
|
+ default=os.cpu_count()-1,
|
|
111
|
+ help="Animation writting threads")
|
108
|
112
|
|
109
|
113
|
args = parser.parse_args()
|
110
|
114
|
|
|
@@ -223,23 +227,16 @@ if 'pool_size' in args:
|
223
|
227
|
else:
|
224
|
228
|
# Generate
|
225
|
229
|
if args.output_dir is not None:
|
226
|
|
- #from PIL import Image
|
227
|
|
- import scipy
|
228
|
|
- def save_anim(data_q):
|
229
|
|
- while True:
|
230
|
|
- wval, fname = data_q.get()
|
231
|
|
- if wval is None:
|
232
|
|
- return
|
233
|
|
- #im = Image.fromarray(wval, 'RGB')
|
234
|
|
- #im.save(fname)
|
235
|
|
- scipy.misc.imsave(fname, wval)
|
236
|
|
- logger.info('Written %s / %d' % (fname, args.steps//args.anim_div))
|
237
|
|
-
|
238
|
|
- data_q = Queue()
|
239
|
|
- wps = [Process(target=save_anim, args=(data_q,))
|
240
|
|
- for _ in range(args.threads)]
|
241
|
|
- for wp in wps:
|
242
|
|
- wp.start()
|
|
230
|
+ from PIL import Image
|
|
231
|
+ def save_pool(im, fname):
|
|
232
|
+ st1 = time.time()
|
|
233
|
+ im.save(fname)
|
|
234
|
+ logger.debug('Image %s saved in %.3fs' % (fname,
|
|
235
|
+ time.time() - st1))
|
|
236
|
+
|
|
237
|
+ write_pool = Pool(args.threads)
|
|
238
|
+ async_res = []
|
|
239
|
+ img_count = 0
|
243
|
240
|
w = World(args.world_height, args.world_width, gray=args.gray)
|
244
|
241
|
prog = rpnlib.RpnExpr.from_string(args.prog)
|
245
|
242
|
turmits = [LivingTurmit(world=w, prog=prog, diag=not args.no_diagonals)
|
|
@@ -256,21 +253,59 @@ else:
|
256
|
253
|
logger.info(msg)
|
257
|
254
|
for turmit in turmits:
|
258
|
255
|
turmit()
|
259
|
|
- if args.output_dir is not None and step % args.anim_div == 0:
|
260
|
|
- fname = 'GTE_ANIM_%d.png' % (step/args.anim_div)
|
|
256
|
+ if args.output_dir is not None and (args.anim_div <= 1 or
|
|
257
|
+ step % (args.anim_div-1) == 0):
|
|
258
|
+ imgid = step // (1 if args.anim_div <= 1 else args.anim_div)
|
|
259
|
+ img_count += 1
|
|
260
|
+ fname = args.anim_fmt % imgid
|
261
|
261
|
fname = os.path.join(args.output_dir, fname)
|
262
|
|
- data_q.put((w._val, fname))
|
263
|
|
- #if args.output_dir is not None and step % args.anim_div == 0:
|
264
|
|
- # #w.save('/tmp/anim/GTE_ANIM_%d.png' % (step/10))
|
265
|
|
- # fname = 'GTE_ANIM_%d?png' % (step/args.anim_div)
|
266
|
|
- # w.save(os.path.join(args.output_dir, fname))
|
|
262
|
+ im = Image.fromarray(np.uint8(w._val))
|
|
263
|
+ async_res.append(write_pool.apply_async(save_pool, (im, fname)))
|
|
264
|
+ while async_res[0].ready():
|
|
265
|
+ async_res[0].get()
|
|
266
|
+ async_res.pop(0)
|
267
|
267
|
|
268
|
268
|
if args.output_dir is not None:
|
269
|
|
- for _ in wps:
|
270
|
|
- data_q.put((None, None))
|
271
|
|
- for wp in wps:
|
272
|
|
- wp.join()
|
273
|
|
- data_q.close()
|
|
269
|
+ while async_res[0].ready():
|
|
270
|
+ async_res[0].get()
|
|
271
|
+ sync_res.pop(0)
|
|
272
|
+ write_pool.close()
|
|
273
|
+ logger.info('Waiting for animation to be written on disk')
|
|
274
|
+ img_st1 = None
|
|
275
|
+ while len(async_res) > 0:
|
|
276
|
+ async_res[0].get()
|
|
277
|
+ async_res.pop(0)
|
|
278
|
+ stat_upd = 100
|
|
279
|
+ if len(async_res) % stat_upd == 0:
|
|
280
|
+ msg = '%d images left' % (len(async_res))
|
|
281
|
+ stupd = stat_upd
|
|
282
|
+ if img_st1 is None:
|
|
283
|
+ img_st1 = start
|
|
284
|
+ stupd = img_count - len(async_res)
|
|
285
|
+ img_st2 = time.time()
|
|
286
|
+ img_st = (img_st2 - img_st1) / stupd
|
|
287
|
+ img_ts = stupd / (img_st2 - img_st1)
|
|
288
|
+ etcs = ''
|
|
289
|
+ if img_st1 != start:
|
|
290
|
+ etc = len(async_res) * img_st
|
|
291
|
+ etcs = ' ETC:'
|
|
292
|
+ if etc >= 60:
|
|
293
|
+ etcs += '%d min ' % (etc // 60)
|
|
294
|
+ etc %= 60
|
|
295
|
+ etcs += '%ds' % etc
|
|
296
|
+ msg += ' %.1fimg/s%s' % (img_ts, etcs)
|
|
297
|
+ img_st1 = img_st2
|
|
298
|
+ logger.info(msg)
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+ write_pool.join()
|
|
303
|
+ #for _ in wps:
|
|
304
|
+ # data_q.put((None, None))
|
|
305
|
+ #for wp in wps:
|
|
306
|
+ # wp.join()
|
|
307
|
+ #data_q.close()
|
|
308
|
+ logger.info('Animation written in "%s"' % args.output_dir)
|
274
|
309
|
stop = time.time()
|
275
|
310
|
|
276
|
311
|
score_dir = sum([t.dirvar() for t in turmits]) / len(turmits)
|