@@ -1534,6 +1534,9 @@ class AthenaSplitterJob(ISplitter):
15341534 'numfiles_subjob' : SimpleItem (defvalue = 0 ,sequence = 0 , doc = "Number of files per subjob" ),
15351535 'match_subjobs_files' : SimpleItem (defvalue = False ,sequence = 0 , doc = "Match the number of subjobs to the number of inputfiles" ),
15361536 'split_per_dataset' : SimpleItem (defvalue = False ,sequence = 0 , doc = "Match the number of subjobs to the number of datasets" ),
1537+ 'events_per_subjob' : SimpleItem (defvalue = - 1 ,sequence = 0 , doc = 'Number of Events to process per subjob. Must be used with numsubjobs.'
1538+ 'The total events processed with be events_per_subjob * numsubjobs. Please'
1539+ 'make sure this covers the number of events required' ),
15371540 'output_loc_to_input' : SimpleItem (defvalue = {}, doc = 'Dictionary that lists the input files that should go to a '
15381541 'particular output dir, e.g. { "/out/dir": ["/in/file1", "/in/file2"].'
15391542 'Input files must match what is given to ATLASLocalDataset }' )
@@ -1554,11 +1557,12 @@ def split(self,job):
15541557 # Preparation
15551558 inputnames = []
15561559 inputguids = []
1557- if job .inputdata :
1560+ if job .inputdata and ( job . inputdata . _name == 'ATLASLocalDataset' ) :
15581561
1559- if (job .inputdata ._name == 'ATLASLocalDataset' ):
1560- inputnames = []
1561- outputnames = []
1562+ # Special case for events_per_subjob as input data is ignored
1563+ inputnames = []
1564+ outputnames = []
1565+ if self .events_per_subjob < 0 :
15621566 numfiles = len (job .inputdata .get_dataset_filenames ())
15631567 if self .numfiles_subjob > 0 :
15641568 self .numsubjobs = int ( math .ceil ( numfiles / float (self .numfiles_subjob ) ) )
@@ -1631,50 +1635,21 @@ def split(self,job):
16311635
16321636 for j in xrange (numfiles ):
16331637 inputnames [j % self .numsubjobs ].append (job .inputdata .get_dataset_filenames ()[j ])
1638+ else :
1639+ # for splitting on events, all data is passed to every subjob and skip events/max events
1640+ # is set appropriately
1641+ if self .numfiles_subjob > 0 or self .match_subjobs_files or self .split_per_dataset :
1642+ raise ApplicationConfigurationError ("Cannot use events_per_subjob with numfiles_subjob, match_subjobs_files, split_per_dataset" )
16341643
1635- if job .inputdata ._name == 'DQ2Dataset' :
1636- # Splitting per dataset
1637- if self .split_per_dataset :
1638- contents = job .inputdata .get_contents (overlap = False )
1639- datasets = job .inputdata .dataset
1640- self .numsubjobs = len (datasets )
1641- for dataset in datasets :
1642- content = contents [dataset ]
1643- content .sort (lambda x ,y :cmp (x [1 ],y [1 ]))
1644- inputnames .append ( [ lfn for guid , lfn in content ] )
1645- inputguids .append ( [ guid for guid , lfn in content ] )
1646- else :
1647- # Splitting per file
1648- content = []
1649- input_files = []
1650- input_guids = []
1651- names = None
1652- # Get list of filenames and guids
1653- contents = job .inputdata .get_contents ()
1654- if self .match_subjobs_files :
1655- self .numsubjobs = len (contents )
1656- elif self .numfiles_subjob > 0 :
1657- numjobs = len (contents ) / int (self .numfiles_subjob )
1658- if (len (contents ) % self .numfiles_subjob )> 0 :
1659- numjobs += 1
1660- self .numsubjobs = numjobs
1661- logger .info ('Submitting %s subjobs' ,numjobs )
1662-
1663- # Fill dummy values
1664- for i in xrange (self .numsubjobs ):
1665- inputnames .append ([])
1666- inputguids .append ([])
1667- input_files = [ lfn for guid , lfn in contents ]
1668- input_guids = [ guid for guid , lfn in contents ]
1644+ if self .numsubjobs < 1 :
1645+ raise ApplicationConfigurationError ("Please specify the number of subjobs if using events_per_subjob" )
16691646
1670- # Splitting
1671- for j in xrange (len (input_files )):
1672- inputnames [j % self .numsubjobs ].append (input_files [j ])
1673- inputguids [j % self .numsubjobs ].append (input_guids [j ])
1647+ logger .warning ("Splitting by number of events. All data will be passed to all subjobs and the total number of events to be"
1648+ "processed will be numsubjobs * events_per_subjob (%d * %d = %d in this case)" %
1649+ (self .numsubjobs , self .events_per_subjob , self .numsubjobs * self .events_per_subjob ))
16741650
1675- if job .backend ._name == 'LCG' and job .backend .middleware == 'GLITE' and self .numsubjobs > config ['MaxJobsAthenaSplitterJobLCG' ]:
1676- printout = 'Job submission failed ! AthenaSplitterJob.numsubjobs>%s - glite WMS does not like bulk jobs with more than approximately 100 subjobs - use less subjobs or use job.backend.middleware=="EDG" ' % config ['MaxJobsAthenaSplitterJobLCG' ]
1677- raise ApplicationConfigurationError (printout )
1651+ for j in xrange (self .numsubjobs ):
1652+ inputnames .append (job .inputdata .get_dataset_filenames ())
16781653
16791654 # Do the splitting
16801655 for i in range (self .numsubjobs ):
@@ -1683,93 +1658,25 @@ def split(self,job):
16831658 j .inputdata = job .inputdata
16841659 if job .inputdata :
16851660 j .inputdata .names = inputnames [i ]
1686- if job .inputdata ._name == 'DQ2Dataset' :
1687- j .inputdata .guids = inputguids [i ]
1688- j .inputdata .number_of_files = len (inputguids [i ])
1689- if self .split_per_dataset :
1690- j .inputdata .dataset = job .inputdata .dataset [i ]
1661+
16911662 j .outputdata = job .outputdata
16921663
16931664 # Set the output location if we have mapping
16941665 if self .output_loc_to_input and isinstance (job .outputdata , ATLASOutputDataset ):
16951666 j .outputdata .location = outputnames [i ]
16961667
16971668 j .application = job .application
1669+ if self .events_per_subjob > 0 :
1670+ j .application .max_events = self .events_per_subjob
1671+ j .application .skip_events = self .events_per_subjob * i
1672+
16981673 j .backend = job .backend
16991674 j .inputsandbox = job .inputsandbox
17001675 j .outputsandbox = job .outputsandbox
17011676
17021677 subjobs .append (j )
17031678 return subjobs
17041679
1705- class ATLASTier3Splitter (ISplitter ):
1706- """Splitter for ATLASTier3Dataset"""
1707-
1708- _name = "ATLASTier3Splitter"
1709- _schema = Schema (Version (1 ,0 ), {
1710- 'numjobs' : SimpleItem (defvalue = 0 ,sequence = 0 , doc = "Number of subjobs" ),
1711- 'numfiles' : SimpleItem (defvalue = 0 ,sequence = 0 , doc = "Number of files per subjob" )
1712- } )
1713-
1714- _GUIPrefs = [ { 'attribute' : 'numjobs' , 'widget' : 'Int' },
1715- { 'attribute' : 'numfiles' , 'widget' : 'Int' },
1716- ]
1717-
1718- ### Splitting based on numsubjobs
1719- def split (self ,job ):
1720- from Ganga .GPIDev .Lib .Job import Job
1721- subjobs = []
1722- logger .debug ("ATLASTier3Splitter split called" )
1723-
1724- if not job .inputdata :
1725- raise ApplicationConfigurationError ("ATLASTier3Splitter requires ATLASTier3Dataset" )
1726- if job .inputdata ._name != 'ATLASTier3Dataset' :
1727- raise ApplicationConfigurationError ("ATLASTier3Splitter requires ATLASTier3Dataset" )
1728- if self .numjobs and self .numfiles :
1729- logger .warning ('You specified numjobs and numfiles. Setting numjobs = 0 to continue.' )
1730- self .numjobs = 0
1731- #raise ApplicationConfigurationError(None, "ATLASTier3Splitter: specify numjobs or numfiles, but not both.")
1732-
1733- if job .inputdata .pfnListFile .name :
1734- logger .info ('Loading file names from %s' % job .inputdata .pfnListFile .name )
1735- pfnListFile = open (job .inputdata .pfnListFile .name )
1736- job .inputdata .names = [name .strip () for name in pfnListFile ]
1737- pfnListFile .close ()
1738-
1739- allnames = list (job .inputdata .names )
1740-
1741- # default behaviour is 20 subjobs
1742- if not self .numjobs and not self .numfiles :
1743- self .numjobs = min (20 ,len (allnames ))
1744-
1745- # limit numfiles and numjobs
1746- self .numjobs = min (self .numjobs ,len (allnames ))
1747- self .numfiles = min (self .numfiles ,len (allnames ))
1748-
1749- # calculate numfiles and numjobs
1750- if self .numfiles :
1751- (self .numjobs ,r ) = divmod (len (allnames ),self .numfiles )
1752- if r : self .numjobs += 1
1753- elif self .numjobs :
1754- (self .numfiles ,r ) = divmod (len (allnames ),self .numjobs )
1755- if r : self .numfiles += 1
1756-
1757- # Do the splitting
1758- allnames .reverse ()
1759- for i in range (self .numjobs ):
1760- j = Job ()
1761- j .inputdata = job .inputdata
1762- j .inputdata .names = []
1763- while allnames and len (j .inputdata .names ) < self .numfiles :
1764- j .inputdata .names .append (allnames .pop ())
1765- j .outputdata = job .outputdata
1766- j .application = job .application
1767- j .backend = job .backend
1768- j .inputsandbox = job .inputsandbox
1769- j .outputsandbox = job .outputsandbox
1770- subjobs .append (j )
1771-
1772- return subjobs
17731680
17741681from Ganga .GPIDev .Adapters .IMerger import IMerger
17751682from commands import getstatusoutput
0 commit comments