Skip to content

Commit

Permalink
Prototype of a helper function
Browse files Browse the repository at this point in the history
  • Loading branch information
makortel committed Sep 4, 2018
1 parent 694edbd commit 7447c89
Show file tree
Hide file tree
Showing 18 changed files with 206 additions and 30 deletions.
4 changes: 4 additions & 0 deletions HeterogeneousCore/CUDATest/python/prod1CPU_cfi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import FWCore.ParameterSet.Config as cms

from HeterogeneousCore.CUDATest.testCUDAProducerCPU_cfi import testCUDAProducerCPU as _testCUDAProducerCPU
prod1CPU = _testCUDAProducerCPU.clone()
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import FWCore.ParameterSet.Config as cms

from HeterogeneousCore.CUDACore.cudaDeviceChooserFilter_cfi import cudaDeviceChooserFilter as _cudaDeviceChooserFilter
prod1CUDADeviceFilter = _cudaDeviceChooserFilter.clone()
4 changes: 4 additions & 0 deletions HeterogeneousCore/CUDATest/python/prod1CUDA_cfi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import FWCore.ParameterSet.Config as cms

from HeterogeneousCore.CUDATest.testCUDAProducerGPUFirst_cfi import testCUDAProducerGPUFirst as _testCUDAProducerGPUFirst
prod1CUDA = _testCUDAProducerGPUFirst.clone(src = "prod1CUDADeviceFilter")
4 changes: 4 additions & 0 deletions HeterogeneousCore/CUDATest/python/prod1FromCUDA_cfi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import FWCore.ParameterSet.Config as cms

from HeterogeneousCore.CUDATest.testCUDAProducerGPUtoCPU_cfi import testCUDAProducerGPUtoCPU as _testCUDAProducerGPUtoCPU
prod1FromCUDA = _testCUDAProducerGPUtoCPU.clone(src = "prod1CUDA")
23 changes: 23 additions & 0 deletions HeterogeneousCore/CUDATest/python/prod1_cff.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import FWCore.ParameterSet.Config as cms

from HeterogeneousCore.CUDATest.prod1CUDADeviceFilter_cfi import prod1CUDADeviceFilter
from HeterogeneousCore.CUDATest.prod1CPU_cfi import prod1CPU
from HeterogeneousCore.CUDATest.prod1CUDA_cfi import prod1CUDA
from HeterogeneousCore.CUDATest.prod1FromCUDA_cfi import prod1FromCUDA

from HeterogeneousCore.CUDATest.testCUDAProducerFallback_cfi import testCUDAProducerFallback as _testCUDAProducerFallback

prod1 = _testCUDAProducerFallback.clone(src = ["prod1CUDA", "prod1CPU"])

prod1PathCUDA = cms.Path(
prod1CUDADeviceFilter +
prod1CUDA
)
prod1PathCPU = cms.Path(
~prod1CUDADeviceFilter +
prod1CPU
)

prod1Task = cms.Task(
prod1FromCUDA, prod1
)
4 changes: 4 additions & 0 deletions HeterogeneousCore/CUDATest/python/prod5CPU_cfi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import FWCore.ParameterSet.Config as cms

from HeterogeneousCore.CUDATest.testCUDAProducerCPU_cfi import testCUDAProducerCPU as _testCUDAProducerCPU
prod5CPU = _testCUDAProducerCPU.clone()
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import FWCore.ParameterSet.Config as cms

from HeterogeneousCore.CUDACore.cudaDeviceChooserFilter_cfi import cudaDeviceChooserFilter as _cudaDeviceChooserFilter
prod5CUDADeviceFilter = _cudaDeviceChooserFilter.clone()
4 changes: 4 additions & 0 deletions HeterogeneousCore/CUDATest/python/prod5CUDA_cfi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import FWCore.ParameterSet.Config as cms

from HeterogeneousCore.CUDATest.testCUDAProducerGPUFirst_cfi import testCUDAProducerGPUFirst as _testCUDAProducerGPUFirst
prod5CUDA = _testCUDAProducerGPUFirst.clone(src = "prod5CUDADeviceFilter")
4 changes: 4 additions & 0 deletions HeterogeneousCore/CUDATest/python/prod5Fallback_cfi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import FWCore.ParameterSet.Config as cms

from HeterogeneousCore.CUDATest.testCUDAProducerFallback_cfi import testCUDAProducerFallback as _testCUDAProducerFallback
prod5Fallback = _testCUDAProducerFallback.clone()
4 changes: 4 additions & 0 deletions HeterogeneousCore/CUDATest/python/prod5FromCUDA_cfi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import FWCore.ParameterSet.Config as cms

from HeterogeneousCore.CUDATest.testCUDAProducerGPUtoCPU_cfi import testCUDAProducerGPUtoCPU as _testCUDAProducerGPUtoCPU
prod5FromCUDA = _testCUDAProducerGPUtoCPU.clone(src = "pro56CUDA")
9 changes: 9 additions & 0 deletions HeterogeneousCore/CUDATest/python/prod5_cff.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import FWCore.ParameterSet.Config as cms

from HeterogeneousCore.CUDATest.prod5CUDADeviceFilter_cfi import prod5CUDADeviceFilter

# The prod6 is the final, (legacy) CPU-only product name, and the
# prod6Task is the Task containing all modules. The function itself
# sets up everything else.
from HeterogeneousCore.CUDATest.setupHeterogeneous import setupCUDA
(prod5, prod5Task) = setupCUDA("prod5", prod5CUDADeviceFilter, globals())
4 changes: 4 additions & 0 deletions HeterogeneousCore/CUDATest/python/prod6CPU_cfi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import FWCore.ParameterSet.Config as cms

from HeterogeneousCore.CUDATest.testCUDAProducerCPU_cfi import testCUDAProducerCPU as _testCUDAProducerCPU
prod6CPU = _testCUDAProducerCPU.clone(src = "prod5CPU")
4 changes: 4 additions & 0 deletions HeterogeneousCore/CUDATest/python/prod6CUDA_cfi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import FWCore.ParameterSet.Config as cms

from HeterogeneousCore.CUDATest.testCUDAProducerGPU_cfi import testCUDAProducerGPU as _testCUDAProducerGPU
prod6CUDA = _testCUDAProducerGPU.clone(src = "prod5CUDA")
4 changes: 4 additions & 0 deletions HeterogeneousCore/CUDATest/python/prod6Fallback_cfi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import FWCore.ParameterSet.Config as cms

from HeterogeneousCore.CUDATest.testCUDAProducerFallback_cfi import testCUDAProducerFallback as _testCUDAProducerFallback
prod6Fallback = _testCUDAProducerFallback.clone()
4 changes: 4 additions & 0 deletions HeterogeneousCore/CUDATest/python/prod6FromCUDA_cfi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import FWCore.ParameterSet.Config as cms

from HeterogeneousCore.CUDATest.testCUDAProducerGPUtoCPU_cfi import testCUDAProducerGPUtoCPU as _testCUDAProducerGPUtoCPU
prod6FromCUDA = _testCUDAProducerGPUtoCPU.clone(src = "prod6CUDA")
9 changes: 9 additions & 0 deletions HeterogeneousCore/CUDATest/python/prod6_cff.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import FWCore.ParameterSet.Config as cms

from HeterogeneousCore.CUDATest.prod5CUDADeviceFilter_cfi import prod5CUDADeviceFilter

# The prod6 is the final, (legacy) CPU-only product name, and the
# prod6Task is the Task containing all modules. The function itself
# sets up everything else.
from HeterogeneousCore.CUDATest.setupHeterogeneous import setupHeterogeneous
(prod6, prod6Task) = setupHeterogeneous("prod6", ["CUDA", "CPU"], {"CUDA": prod5CUDADeviceFilter}, globals())
101 changes: 101 additions & 0 deletions HeterogeneousCore/CUDATest/python/setupHeterogeneous.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import FWCore.ParameterSet.Config as cms

# Prototype of the function
import importlib
def setupHeterogeneous(prefix, deviceTypes, deviceFilters, modDict,
package=None, transferModuleNames={}, fallbackModuleName=None):
"""
Mandatory parameters:
prefix -- common prefix of the CPU, CUDA, etc producers
deviceTypes -- list of strings for the device types
deviceFilters -- dict of non-CPU device types to device filter modules
modDict -- globals()
Optional parameters:
package -- Package of the modules (default None signals to use the current package)
transferModuleName -- Dictionary for names of the device->CPU modules to be loaded and inserted in modDict (if the dictionary does not contain a key 'prefix', a default value of 'prefix+'From<device>' will be used)
fallbackModuleName -- Name of the devices+CPU product fallback producer to be loaded (default None means prefix+'Fallback')
Returns a pair of
- something which looks like an EDProducer picking the product from devices+CPU
- Task containing all the added modules
"""
path = ""
if package is None:
pkgs = __name__.split(".")
if len(pkgs) > 1:
path = ".".join(pkgs[:-1])+"."
else:
path = package+"."

# Per-device producers
for dt in deviceTypes:
modName = prefix+dt
pkg = importlib.import_module(path+modName+"_cfi")
mod = getattr(pkg, modName)
modDict[modName] = mod

# device->CPU
for dt in deviceTypes:
if dt == "CPU":
continue
transferModName = transferModuleNames.get(dt, prefix+"From"+dt)

transferModPath = path+transferModName+"_cfi"
transferModPkg = importlib.import_module(transferModPath)
transferMod = getattr(transferModPkg, transferModName).clone(src=prefix+dt)
modDict[transferModName] = transferMod

# Fallback
if fallbackModuleName is None:
fallbackModName = prefix+"Fallback"
else:
fallbackModName = fallbackModuleName
fallbackModPath = path+fallbackModName+"_cfi"
fallbackModPkg = importlib.import_module(fallbackModPath)
def _from(s):
if s == "CPU":
return s
return "From"+s
fallback = getattr(fallbackModPkg, fallbackModName).clone(src=[prefix+_from(dt) for dt in deviceTypes])

# Paths
tmp = {}
for dt in deviceTypes:
tmp[dt] = cms.Path()

for dt in deviceTypes:
p = cms.Path()

# Add inverted filters until the current device type is found, then insert filter and stop
# For [CUDA, FPGA, CPU] results in
# CUDA: CUDAFilter
# FPGA: ~CUDAFilter + FPGAFilter
# CPU: ~CUDAFilter + ~FPGAFilter
for dt2 in deviceTypes:
if dt2 == "CPU":
continue
filt = deviceFilters[dt2]
if dt2 == dt:
p += filt
break
else:
p += ~filt

# Finally add the producer of the type
p += modDict[prefix+dt]

modDict[prefix+"Path"+dt] = p

# Task
task = cms.Task(transferMod, fallback)

return (fallback, task)

def setupCUDA(prefix, deviceFilter, modDict,
package=None, transferModule=None, **kwargs):
transfer = {}
if transferModule is not None:
transfer["CUDA"] = transferModule
return setupHeterogeneous(prefix, ["CUDA", "CPU"], {"CUDA": deviceFilter}, modDict,
package, transfer, **kwargs)
42 changes: 12 additions & 30 deletions HeterogeneousCore/CUDATest/test/testCUDA_cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,52 +17,44 @@
# Flow diagram of the modules
#
# 1 5
# / \
# 2 4
# / \ |
# 2 4 6
# |
# 3
#

process.load("HeterogeneousCore.CUDATest.prod1_cff")
process.load("HeterogeneousCore.CUDATest.prod5_cff")
process.load("HeterogeneousCore.CUDATest.prod6_cff")

# CPU producers
from HeterogeneousCore.CUDATest.testCUDAProducerCPU_cfi import testCUDAProducerCPU
process.prod1CPU = testCUDAProducerCPU.clone()
process.prod2CPU = testCUDAProducerCPU.clone(src = "prod1CPU")
process.prod3CPU = testCUDAProducerCPU.clone(src = "prod2CPU")
process.prod4CPU = testCUDAProducerCPU.clone(src = "prod1CPU")
process.prod5CPU = testCUDAProducerCPU.clone()

# Module to decide whether the chain of CUDA modules are run, and to disable a Path in case we don't run on CUDA
from HeterogeneousCore.CUDACore.cudaDeviceChooserFilter_cfi import cudaDeviceChooserFilter
process.prodCUDADeviceFilter = cudaDeviceChooserFilter.clone()

from HeterogeneousCore.CUDATest.testCUDAProducerGPUFirst_cfi import testCUDAProducerGPUFirst
from HeterogeneousCore.CUDATest.testCUDAProducerGPU_cfi import testCUDAProducerGPU
from HeterogeneousCore.CUDATest.testCUDAProducerGPUEW_cfi import testCUDAProducerGPUEW
from HeterogeneousCore.CUDATest.testCUDAProducerGPUtoCPU_cfi import testCUDAProducerGPUtoCPU

# GPU producers
process.prod1CUDA = testCUDAProducerGPUFirst.clone(src = "prodCUDADeviceFilter")
process.prod2CUDA = testCUDAProducerGPU.clone(src = "prod1CUDA")
process.prod3CUDA = testCUDAProducerGPU.clone(src = "prod2CUDA")
process.prod4CUDA = testCUDAProducerGPUEW.clone(src = "prod1CUDA")
process.prod5CUDA = testCUDAProducerGPUFirst.clone(src = "prodCUDADeviceFilter")

# Modules to copy data from GPU to CPU (as "on demand" as any other
# EDProducer, i.e. according to consumes() and prefetching)
process.prod1FromCUDA = testCUDAProducerGPUtoCPU.clone(src = "prod1CUDA")
process.prod2FromCUDA = testCUDAProducerGPUtoCPU.clone(src = "prod2CUDA")
process.prod3FromCUDA = testCUDAProducerGPUtoCPU.clone(src = "prod3CUDA")
process.prod4FromCUDA = testCUDAProducerGPUtoCPU.clone(src = "prod4CUDA")
process.prod5FromCUDA = testCUDAProducerGPUtoCPU.clone(src = "prod5CUDA")

# These ones are to provide backwards compatibility to the downstream
# clients. To be replaced with an enhanced version of EDAlias (with an
# ordered fallback mechanism).
from HeterogeneousCore.CUDATest.testCUDAProducerFallback_cfi import testCUDAProducerFallback
process.prod1 = testCUDAProducerFallback.clone(src = ["prod1FromCUDA", "prod1CPU"])
process.prod2 = testCUDAProducerFallback.clone(src = ["prod2FromCUDA", "prod2CPU"])
process.prod3 = testCUDAProducerFallback.clone(src = ["prod3FromCUDA", "prod3CPU"])
process.prod4 = testCUDAProducerFallback.clone(src = ["prod4FromCUDA", "prod4CPU"])
process.prod5 = testCUDAProducerFallback.clone(src = ["prod5FromCUDA", "prod5CPU"])

process.out = cms.OutputModule("AsciiOutputModule",
outputCommands = cms.untracked.vstring(
Expand All @@ -74,38 +66,28 @@
)

process.prodCPU1 = cms.Path(
~process.prodCUDADeviceFilter +
process.prod1CPU +
~process.prod1CUDADeviceFilter +
process.prod2CPU +
process.prod3CPU +
process.prod4CPU
)
process.prodCUDA1 = cms.Path(
process.prodCUDADeviceFilter +
process.prod1CUDA +
process.prod1CUDADeviceFilter +
process.prod2CUDA +
process.prod3CUDA +
process.prod4CUDA
)

process.prodCPU5 = cms.Path(
~process.prodCUDADeviceFilter +
process.prod5CPU
)
process.prodCUDA5 = cms.Path(
process.prodCUDADeviceFilter +
process.prod5CUDA
)

process.t = cms.Task(
# Eventually the goal is to specify these as part of a Task,
# but (at least) as long as the fallback mechanism is implemented
# with an EDProducer, they must be in a Path.
# process.prod2CPU, process.prod3CPU, process.prod4CPU,
# process.prod2CUDA, process.prod3CUDA, process.prod4CUDA,

process.prod1FromCUDA, process.prod2FromCUDA, process.prod3FromCUDA, process.prod4FromCUDA, process.prod5FromCUDA,
process.prod1, process.prod2, process.prod3, process.prod4, process.prod5,
process.prod2FromCUDA, process.prod3FromCUDA, process.prod4FromCUDA,
process.prod2, process.prod3, process.prod4,
process.prod1Task, process.prod5Task, process.prod6Task
)
process.p = cms.Path()
process.p.associate(process.t)
Expand Down

0 comments on commit 7447c89

Please sign in to comment.