"""
This module has utilities to benchmark paraview.
You can set up arbitrary pipelines and this module helps you obtain,
interpret and report the information recorded by ParaView's logs.
Do that like so:
1. Optionally, call maximize logs first
2. Setup and run your visualization pipeline (via GUI or script as you prefer)
3. Call print_logs() to print out the logs in raw format
"""
from __future__ import print_function
from paraview.simple import *
import paraview
start_frame = 0
default_log_threshold = dict()
[docs]def component_to_string(comp):
session = servermanager.ProxyManager().GetSessionProxyManager().GetSession()
if comp == session.NONE: return 'None'
if comp == session.DATA_SERVER: return 'DataServer'
if comp == session.DATA_SERVER_ROOT: return 'DataServerRoot'
if comp == session.RENDER_SERVER: return 'RenderServer'
if comp == session.RENDER_SERVER_ROOT: return 'RenderServerRoot'
if comp == session.SERVERS: return 'Servers'
if comp == session.CLIENT: return 'Client'
if comp == session.CLIENT_AND_SERVERS: return 'ClientAndServers'
return None
[docs]class OneLog:
def __init__(self, runmode='batch', servertype='unified', component=0, rank=0):
self.runmode = runmode
self.servertype = servertype
self.component = component_to_string(component)
self.rank = rank
self.lines = []
[docs] def print_log(self, showlines=False):
print("#RunMode:", self.runmode, end="")
print("ServerType:", self.servertype, end="")
print("Component:", self.component, end="")
print("processor#:", self.rank)
if showlines:
for i in self.lines:
print(i)
[docs] def toString(self, showlines=False):
result = "#RunMode: " + self.runmode + " ServerType: " + self.servertype + " processor#: " + str(
self.rank) + "\n"
if showlines:
for i in self.lines:
result += i + "\n"
return result
logs = []
[docs]def maximize_logs():
"""
Convenience method to ask paraview to produce logs with lots of space and
highest resolution.
"""
pm = paraview.servermanager.vtkProcessModule.GetProcessModule()
if pm == None:
return
ss = paraview.servermanager.vtkSMSession
for ptype in [ss.CLIENT_AND_SERVERS, ss.CLIENT, ss.SERVERS,
ss.RENDER_SERVER, ss.DATA_SERVER]:
default_log_threshold[str(ptype)] = 0.0
pxm = paraview.servermanager.ProxyManager()
tl = pxm.NewProxy("misc", "TimerLog")
prop = tl.GetProperty("MaxEntries")
prop.SetElements1(1000000)
tl.UpdateVTKObjects()
[docs]def get_memuse():
pm = paraview.servermanager.vtkProcessModule.GetProcessModule()
session = servermanager.ProxyManager().GetSessionProxyManager().GetSession()
retval = []
if pm.GetProcessTypeAsInt() == pm.PROCESS_BATCH:
components = {'CL_DS_RS': session.CLIENT_AND_SERVERS}
else:
if session.GetRenderClientMode() == session.RENDERING_UNIFIED:
components = {'CL': session.CLIENT, 'DS_RS': session.SERVERS}
else:
components = {'CL': session.CLIENT, 'RS': session.RENDER_SERVER, 'DS': session.DATA_SERVER}
for comp_label, comp_type in components.items():
infos = servermanager.vtkPVMemoryUseInformation()
session.GatherInformation(comp_type, infos, 0)
for i in range(0, infos.GetSize()):
retval.append('%(l)s[%(r)d] %(pu)d / %(hu)d' %
{'l': comp_label, 'r': infos.GetRank(i),
'pu': infos.GetProcMemoryUse(i),
'hu': infos.GetHostMemoryUse(i)})
return retval
[docs]def dump_logs(filename):
"""
This saves off the logs we've gathered.
Ot allows you to run a benchmark somewhere, save off all of the details in
raw format, then load them somewhere else. You can then do a detailed
analysis and you always have the raw data to go back to.
"""
import pickle
global logs
if sys.version_info < (3,):
f = open(filename, "w")
else:
f = open(filename, "wb")
pickle.dump(logs, f)
f.close()
[docs]def import_logs(filename):
"""
This is for bringing in a saved log files and parse it after the fact.
TODO: add an option to load in raw paraview logs in text format
"""
import pickle
global logs
logs = []
if sys.version_info < (3,):
f = open(filename, "r")
else:
f = open(filename, "rb")
logs = pickle.load(f)
f.close()
[docs]def get_logs():
"""
This is for bringing in logs at run time to parse while running.
"""
global logs
logs = []
pm = paraview.servermanager.vtkProcessModule.GetProcessModule()
if pm == None:
return
connectionId = paraview.servermanager.ActiveConnection.ID
session = paraview.servermanager.ActiveConnection.Session
is_symmetric_mode = False
if pm.GetProcessTypeAsInt() == pm.PROCESS_BATCH:
runmode = 'batch'
is_symmetric_mode = pm.GetSymmetricMPIMode()
else:
runmode = 'interactive'
if session.GetRenderClientMode() == session.RENDERING_UNIFIED:
servertype = 'unified'
else:
servertype = 'split'
if runmode == 'batch':
# collect information from all processes in one go.
components = [session.CLIENT_AND_SERVERS]
else:
if servertype == 'unified':
# collect information separately for client and servers.
components = [session.CLIENT, session.SERVERS]
else:
# collect information separately for all process types.
components = [session.CLIENT, session.RENDER_SERVER, session.DATA_SERVER]
for component in components:
timerInfo = paraview.servermanager.vtkPVTimerInformation()
if len(default_log_threshold) != 0:
timerInfo.SetLogThreshold(default_log_threshold[str(component)])
session.GatherInformation(component, timerInfo, 0)
for i in range(timerInfo.GetNumberOfLogs()):
alog = OneLog(runmode, servertype, component, i)
if is_symmetric_mode:
# in Symmetric mode, GatherInformation() only collects
# information from the current node. so the
# vtkPVTimerInformation will only have info for local process.
alog.rank = pm.GetPartitionId()
alog.lines = timerInfo.GetLog(i).split('\n');
logs.append(alog)
[docs]def print_logs():
"""
Print logs on the root node by gathering logs across all the nodes
regardless if the process was started in symmetric mode or not.
"""
global logs
if len(logs) == 0:
get_logs()
# Handle symmetric mode specifically if need be
pm = paraview.servermanager.vtkProcessModule.GetProcessModule()
is_symmetric_mode = False
if pm != None:
is_symmetric_mode = pm.GetSymmetricMPIMode()
if is_symmetric_mode:
# Need to provide extra synchronization
ctrl = pm.GetGlobalController()
proc = pm.GetPartitionId()
nbProc = pm.GetNumberOfLocalPartitions()
if proc == 0:
# Start with my logs
for i in logs:
i.print_log(True)
# Then Print the log of every other rank
for otherProc in range(1, nbProc):
# Max buffer size 999999
logSize = " " * 6
ctrl.Receive(logSize, len(logSize), otherProc, 987455)
logSize = int(logSize)
logTxt = " " * logSize
ctrl.Receive(logTxt, logSize, otherProc, 987456)
print(logTxt)
else:
# Extract logs text
logTxt = ""
for i in logs:
logTxt += i.toString(True)
logSize = str(len(logTxt))
# Push local logs to process 0
ctrl.Send(logSize, len(logSize), 0, 987455)
ctrl.Send(logTxt, len(logTxt), 0, 987456)
else:
# Regular local print
for i in logs:
i.print_log(True)
[docs]def test_module():
"""Simply exercises a few components of the module."""
maximize_logs()
paraview.servermanager.SetProgressPrintingEnabled(0)
ss = Sphere(ThetaResolution=1000, PhiResolution=500)
rep = Show()
v = Render()
print_logs()
if __name__ == "__main__":
test_module()