#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>