#2033: Moving g.pnmcomp to lib/display to improve render performance of wxGUI ----------------------------------------------+----------------------------- Reporter: huhabla | Owner: grass-dev@… Type: enhancement | Status: new Priority: major | Milestone: 7.0.0 Component: wxGUI | Version: svn-trunk Keywords: display, Python, multiprocessing | Platform: All Cpu: All | ----------------------------------------------+-----------------------------
Comment(by huhabla): I have improved the benchmark script and implemented PIL based and g.pnmcomp image composition (without transparency). Now png, bmp and ppm images are created and mmap is enabled for bmp images. Time is measured for the whole rendering/composition process and separately for the composition. My test system is a core-i5 2410M with 8GB RAM and 320Gig HD running Ubuntu 12.04 LTS. It seems to me that creating raw bmp images without mmap enabled shows the best performance for the PNG and Cairo driver. Maybe i did something wrong, but the use of mmap shows no obvious benefit? The png compression slows the rendering significantly down and is IMHO not well suited as image exchange format in the rendering/composition process. Running the render processes in parallel shows only for the 4096x4096 pixel size images a significant benefit. Any suggestions to improve the benchmark? Does my setup produce reasonable results? Here the script: {{{ # -*- coding: utf-8 -*- import os import time import Image import wx from grass.pygrass import modules parallel = [True, False] drivers = ["png", "cairo"] bitmaps = ["png", "bmp", "ppm"] mmap_modes = ["FALSE", "TRUE"] sizes = [1024, 4096] ############################################################################ def render_image(module, driver="png", pngfile="test.png", size=4096, mapped="TRUE"): os.putenv("GRASS_RENDER_IMMEDIATE", "%s"%driver) os.putenv("GRASS_PNGFILE", "%s"%pngfile) os.putenv("GRASS_WIDTH", "%i"%size) os.putenv("GRASS_HEIGHT", "%i"%size) os.putenv("GRASS_PNG_MAPPED", "%s"%mapped) module.run() ############################################################################ def composite_images(files, bitmap, mode, size): start = time.time() if bitmap == "ppm": filename = "output" filename += ".ppm" modules.Module("g.pnmcomp", input=files, width=size, height=size, output=filename) # Load the image as wx image for visualization img = wx.Image(filename, wx.BITMAP_TYPE_ANY) os.remove(filename) else: images = [] size = None for m in files: im = Image.open(m) images.append(im) size = im.size comp = Image.new('RGB', size) for im in images: comp.paste(im) wxImage = wx.EmptyImage(*comp.size) wxImage.SetData(comp.convert('RGB').tostring()) return (time.time() - start) ############################################################################ def main(): # Set the region modules.Module("g.region", rast="elevation", flags="p") for finish in parallel: if finish: print("*** Serial runs") else: print("*** Parallel runs") print("Run\tSize\tDriver\tBitmap\tmmap\trender\tcomposite") # Setup the modules rast = modules.Module("d.rast", map="elevation", run_=False, quiet=True, finish_=False) vectB = modules.Module("d.vect", map="streams", width=1, color="blue", fcolor="aqua", type=["area","line"], run_=False, quiet=True, finish_=finish) vectA = modules.Module("d.vect", map="roadsmajor", width=2, run_=False, quiet=True, finish_=finish) count = 0 for size in sizes: for driver in drivers: for bitmap in bitmaps: for mode in mmap_modes: # Skip mmap for non-bmp files if mode == "TRUE" and bitmap != "bmp": continue start = time.time() count += 1 files = [] rast_file = "rast.%s"%(bitmap) vectA_file="vectA.%s"%(bitmap) vectB_file="vectB.%s"%(bitmap) files.append(rast_file) files.append(vectA_file) files.append(vectB_file) render_image(rast, driver=driver, pngfile=rast_file, size=size, mapped=mode) render_image(vectA, driver=driver, pngfile=vectA_file, size=size, mapped=mode) render_image(vectB, driver=driver, pngfile=vectB_file, size=size, mapped=mode) # Wait for processes rast.popen.wait() vectA.popen.wait() vectB.popen.wait() # Composite the images comptime = composite_images(files, bitmap, mode, size) for file in files: os.remove(file) elapsed = (time.time() - start) print("%i\t%i\t%s\t%s\t%s\t%.2f\t%.2f"%(count, size, driver, bitmap, mode, elapsed, comptime)) ############################################################################ main() }}} Here the benchmark results: {{{ GRASS 7.0.svn (nc_spm_08_grass7):~/src > python display_bench.py projection: 99 (Lambert Conformal Conic) zone: 0 datum: nad83 ellipsoid: a=6378137 es=0.006694380022900787 north: 228500 south: 215000 west: 630000 east: 645000 nsres: 10 ewres: 10 rows: 1350 cols: 1500 cells: 2025000 *** Serial runs Run Size Driver Bitmap mmap render composite 1 1024 png png FALSE 0.87 0.11 2 1024 png bmp FALSE 0.45 0.03 3 1024 png bmp TRUE 0.48 0.03 4 1024 png ppm FALSE 0.47 0.07 5 1024 cairo png FALSE 0.93 0.09 6 1024 cairo bmp FALSE 0.52 0.03 7 1024 cairo bmp TRUE 0.56 0.03 8 1024 cairo ppm FALSE 0.61 0.06 9 4096 png png FALSE 4.74 1.29 10 4096 png bmp FALSE 3.43 0.38 11 4096 png bmp TRUE 4.15 0.38 12 4096 png ppm FALSE 3.04 0.55 13 4096 cairo png FALSE 3.68 0.99 14 4096 cairo bmp FALSE 1.95 0.37 15 4096 cairo bmp TRUE 2.65 0.37 16 4096 cairo ppm FALSE 3.44 0.55 *** Parallel runs Run Size Driver Bitmap mmap render composite 1 1024 png png FALSE 0.92 0.11 2 1024 png bmp FALSE 0.50 0.03 3 1024 png bmp TRUE 0.48 0.03 4 1024 png ppm FALSE 0.51 0.07 5 1024 cairo png FALSE 0.98 0.08 6 1024 cairo bmp FALSE 0.53 0.03 7 1024 cairo bmp TRUE 0.60 0.03 8 1024 cairo ppm FALSE 0.67 0.07 9 4096 png png FALSE 4.77 1.33 10 4096 png bmp FALSE 3.08 0.37 11 4096 png bmp TRUE 3.74 0.38 12 4096 png ppm FALSE 2.84 0.55 13 4096 cairo png FALSE 3.38 1.01 14 4096 cairo bmp FALSE 1.82 0.37 15 4096 cairo bmp TRUE 2.44 0.37 16 4096 cairo ppm FALSE 2.93 0.55 }}} -- Ticket URL: <http://trac.osgeo.org/grass/ticket/2033#comment:6> GRASS GIS <http://grass.osgeo.org> _______________________________________________ grass-dev mailing list grass-dev@lists.osgeo.org http://lists.osgeo.org/mailman/listinfo/grass-dev