diff --git a/HeterogeneousCore/CUDATest/python/prod1CPU_cfi.py b/HeterogeneousCore/CUDATest/python/prod1CPU_cfi.py new file mode 100644 index 0000000000000..421d01c07ea46 --- /dev/null +++ b/HeterogeneousCore/CUDATest/python/prod1CPU_cfi.py @@ -0,0 +1,4 @@ +import FWCore.ParameterSet.Config as cms + +from HeterogeneousCore.CUDATest.testCUDAProducerCPU_cfi import testCUDAProducerCPU as _testCUDAProducerCPU +prod1CPU = _testCUDAProducerCPU.clone() diff --git a/HeterogeneousCore/CUDATest/python/prod1CUDADeviceFilter_cfi.py b/HeterogeneousCore/CUDATest/python/prod1CUDADeviceFilter_cfi.py new file mode 100644 index 0000000000000..c8f9c3574c561 --- /dev/null +++ b/HeterogeneousCore/CUDATest/python/prod1CUDADeviceFilter_cfi.py @@ -0,0 +1,4 @@ +import FWCore.ParameterSet.Config as cms + +from HeterogeneousCore.CUDACore.cudaDeviceChooserFilter_cfi import cudaDeviceChooserFilter as _cudaDeviceChooserFilter +prod1CUDADeviceFilter = _cudaDeviceChooserFilter.clone() diff --git a/HeterogeneousCore/CUDATest/python/prod1CUDA_cfi.py b/HeterogeneousCore/CUDATest/python/prod1CUDA_cfi.py new file mode 100644 index 0000000000000..b333aa78562cb --- /dev/null +++ b/HeterogeneousCore/CUDATest/python/prod1CUDA_cfi.py @@ -0,0 +1,4 @@ +import FWCore.ParameterSet.Config as cms + +from HeterogeneousCore.CUDATest.testCUDAProducerGPUFirst_cfi import testCUDAProducerGPUFirst as _testCUDAProducerGPUFirst +prod1CUDA = _testCUDAProducerGPUFirst.clone(src = "prod1CUDADeviceFilter") diff --git a/HeterogeneousCore/CUDATest/python/prod1FromCUDA_cfi.py b/HeterogeneousCore/CUDATest/python/prod1FromCUDA_cfi.py new file mode 100644 index 0000000000000..de6ed9b0ff179 --- /dev/null +++ b/HeterogeneousCore/CUDATest/python/prod1FromCUDA_cfi.py @@ -0,0 +1,4 @@ +import FWCore.ParameterSet.Config as cms + +from HeterogeneousCore.CUDATest.testCUDAProducerGPUtoCPU_cfi import testCUDAProducerGPUtoCPU as _testCUDAProducerGPUtoCPU +prod1FromCUDA = _testCUDAProducerGPUtoCPU.clone(src = "prod1CUDA") diff --git a/HeterogeneousCore/CUDATest/python/prod1_cff.py b/HeterogeneousCore/CUDATest/python/prod1_cff.py new file mode 100644 index 0000000000000..734609b373ac4 --- /dev/null +++ b/HeterogeneousCore/CUDATest/python/prod1_cff.py @@ -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 +) diff --git a/HeterogeneousCore/CUDATest/python/prod5CPU_cfi.py b/HeterogeneousCore/CUDATest/python/prod5CPU_cfi.py new file mode 100644 index 0000000000000..3353c774f8f27 --- /dev/null +++ b/HeterogeneousCore/CUDATest/python/prod5CPU_cfi.py @@ -0,0 +1,4 @@ +import FWCore.ParameterSet.Config as cms + +from HeterogeneousCore.CUDATest.testCUDAProducerCPU_cfi import testCUDAProducerCPU as _testCUDAProducerCPU +prod5CPU = _testCUDAProducerCPU.clone() diff --git a/HeterogeneousCore/CUDATest/python/prod5CUDADeviceFilter_cfi.py b/HeterogeneousCore/CUDATest/python/prod5CUDADeviceFilter_cfi.py new file mode 100644 index 0000000000000..cfe4f4048b8f3 --- /dev/null +++ b/HeterogeneousCore/CUDATest/python/prod5CUDADeviceFilter_cfi.py @@ -0,0 +1,4 @@ +import FWCore.ParameterSet.Config as cms + +from HeterogeneousCore.CUDACore.cudaDeviceChooserFilter_cfi import cudaDeviceChooserFilter as _cudaDeviceChooserFilter +prod5CUDADeviceFilter = _cudaDeviceChooserFilter.clone() diff --git a/HeterogeneousCore/CUDATest/python/prod5CUDA_cfi.py b/HeterogeneousCore/CUDATest/python/prod5CUDA_cfi.py new file mode 100644 index 0000000000000..ae7f605d07975 --- /dev/null +++ b/HeterogeneousCore/CUDATest/python/prod5CUDA_cfi.py @@ -0,0 +1,4 @@ +import FWCore.ParameterSet.Config as cms + +from HeterogeneousCore.CUDATest.testCUDAProducerGPUFirst_cfi import testCUDAProducerGPUFirst as _testCUDAProducerGPUFirst +prod5CUDA = _testCUDAProducerGPUFirst.clone(src = "prod5CUDADeviceFilter") diff --git a/HeterogeneousCore/CUDATest/python/prod5Fallback_cfi.py b/HeterogeneousCore/CUDATest/python/prod5Fallback_cfi.py new file mode 100644 index 0000000000000..4ad84bdeee4a7 --- /dev/null +++ b/HeterogeneousCore/CUDATest/python/prod5Fallback_cfi.py @@ -0,0 +1,4 @@ +import FWCore.ParameterSet.Config as cms + +from HeterogeneousCore.CUDATest.testCUDAProducerFallback_cfi import testCUDAProducerFallback as _testCUDAProducerFallback +prod5Fallback = _testCUDAProducerFallback.clone() diff --git a/HeterogeneousCore/CUDATest/python/prod5FromCUDA_cfi.py b/HeterogeneousCore/CUDATest/python/prod5FromCUDA_cfi.py new file mode 100644 index 0000000000000..467be55653f4e --- /dev/null +++ b/HeterogeneousCore/CUDATest/python/prod5FromCUDA_cfi.py @@ -0,0 +1,4 @@ +import FWCore.ParameterSet.Config as cms + +from HeterogeneousCore.CUDATest.testCUDAProducerGPUtoCPU_cfi import testCUDAProducerGPUtoCPU as _testCUDAProducerGPUtoCPU +prod5FromCUDA = _testCUDAProducerGPUtoCPU.clone(src = "pro56CUDA") diff --git a/HeterogeneousCore/CUDATest/python/prod5_cff.py b/HeterogeneousCore/CUDATest/python/prod5_cff.py new file mode 100644 index 0000000000000..2b8948551733c --- /dev/null +++ b/HeterogeneousCore/CUDATest/python/prod5_cff.py @@ -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()) diff --git a/HeterogeneousCore/CUDATest/python/prod6CPU_cfi.py b/HeterogeneousCore/CUDATest/python/prod6CPU_cfi.py new file mode 100644 index 0000000000000..1cb1bba3f12b1 --- /dev/null +++ b/HeterogeneousCore/CUDATest/python/prod6CPU_cfi.py @@ -0,0 +1,4 @@ +import FWCore.ParameterSet.Config as cms + +from HeterogeneousCore.CUDATest.testCUDAProducerCPU_cfi import testCUDAProducerCPU as _testCUDAProducerCPU +prod6CPU = _testCUDAProducerCPU.clone(src = "prod5CPU") diff --git a/HeterogeneousCore/CUDATest/python/prod6CUDA_cfi.py b/HeterogeneousCore/CUDATest/python/prod6CUDA_cfi.py new file mode 100644 index 0000000000000..0e1ea6ebbca0f --- /dev/null +++ b/HeterogeneousCore/CUDATest/python/prod6CUDA_cfi.py @@ -0,0 +1,4 @@ +import FWCore.ParameterSet.Config as cms + +from HeterogeneousCore.CUDATest.testCUDAProducerGPU_cfi import testCUDAProducerGPU as _testCUDAProducerGPU +prod6CUDA = _testCUDAProducerGPU.clone(src = "prod5CUDA") diff --git a/HeterogeneousCore/CUDATest/python/prod6Fallback_cfi.py b/HeterogeneousCore/CUDATest/python/prod6Fallback_cfi.py new file mode 100644 index 0000000000000..60e9f1910188e --- /dev/null +++ b/HeterogeneousCore/CUDATest/python/prod6Fallback_cfi.py @@ -0,0 +1,4 @@ +import FWCore.ParameterSet.Config as cms + +from HeterogeneousCore.CUDATest.testCUDAProducerFallback_cfi import testCUDAProducerFallback as _testCUDAProducerFallback +prod6Fallback = _testCUDAProducerFallback.clone() diff --git a/HeterogeneousCore/CUDATest/python/prod6FromCUDA_cfi.py b/HeterogeneousCore/CUDATest/python/prod6FromCUDA_cfi.py new file mode 100644 index 0000000000000..de894a5f32617 --- /dev/null +++ b/HeterogeneousCore/CUDATest/python/prod6FromCUDA_cfi.py @@ -0,0 +1,4 @@ +import FWCore.ParameterSet.Config as cms + +from HeterogeneousCore.CUDATest.testCUDAProducerGPUtoCPU_cfi import testCUDAProducerGPUtoCPU as _testCUDAProducerGPUtoCPU +prod6FromCUDA = _testCUDAProducerGPUtoCPU.clone(src = "prod6CUDA") diff --git a/HeterogeneousCore/CUDATest/python/prod6_cff.py b/HeterogeneousCore/CUDATest/python/prod6_cff.py new file mode 100644 index 0000000000000..7df34426ab67f --- /dev/null +++ b/HeterogeneousCore/CUDATest/python/prod6_cff.py @@ -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()) diff --git a/HeterogeneousCore/CUDATest/python/setupHeterogeneous.py b/HeterogeneousCore/CUDATest/python/setupHeterogeneous.py new file mode 100644 index 0000000000000..0fc5d7980ceeb --- /dev/null +++ b/HeterogeneousCore/CUDATest/python/setupHeterogeneous.py @@ -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' 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) diff --git a/HeterogeneousCore/CUDATest/test/testCUDA_cfg.py b/HeterogeneousCore/CUDATest/test/testCUDA_cfg.py index 0c54569d2b201..e9ddebfaa35b5 100644 --- a/HeterogeneousCore/CUDATest/test/testCUDA_cfg.py +++ b/HeterogeneousCore/CUDATest/test/testCUDA_cfg.py @@ -17,22 +17,20 @@ # 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 @@ -40,29 +38,23 @@ 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( @@ -74,29 +66,18 @@ ) 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 @@ -104,8 +85,9 @@ # 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)