15
15
#include " swift/AST/DiagnosticEngine.h"
16
16
#include " swift/AST/DiagnosticsDriver.h"
17
17
#include " swift/Basic/Program.h"
18
+ #include " swift/Basic/STLExtras.h"
18
19
#include " swift/Basic/Statistic.h"
19
20
#include " swift/Basic/TaskQueue.h"
20
21
#include " swift/Basic/Version.h"
@@ -724,31 +725,31 @@ namespace driver {
724
725
Batches.push_back (Comp.addJob (std::move (J)));
725
726
}
726
727
727
- // / Inspect current batch \p i of the \p Partition currently being built
728
- // / and, if that batch is "full" (in the sense of holding an evenly-divided
729
- // / portion of NumJobs) then advance \p i to the next batch index in the
730
- // / partition.
731
- void maybeAdvanceToNextPartition (size_t &i,
732
- BatchPartition const &Partition,
733
- size_t NumJobs) {
734
- assert (i < Partition.size ());
735
- size_t Remainder = NumJobs % Partition.size ();
736
- size_t TargetSize = NumJobs / Partition.size ();
737
- // Spread remainder evenly across partitions by adding 1 to the target
738
- // size of the first Remainder of them.
739
- if (i < Remainder)
740
- TargetSize++;
741
- if (Partition[i].size () >= TargetSize)
742
- ++i;
743
- assert (i < Partition.size ());
744
- }
745
-
746
- // / Shuffle \p Batchable if -driver-batch-seed is nonzero.
747
- void maybeShuffleBatchable (std::vector<const Job *> &Batchable) {
728
+ // / Build a vector of partition indices, one per Job: the i'th index says
729
+ // / which batch of the partition the i'th Job will be assigned to. If we are
730
+ // / shuffling due to -driver-batch-seed, the returned indices will not be
731
+ // / arranged in contiguous runs. We shuffle partition-indices here, not
732
+ // / elements themselves, to preserve the invariant that each batch is a
733
+ // / subsequence of the full set of inputs, not just a subset.
734
+ std::vector<size_t >
735
+ assignJobsToPartitions (size_t PartitionSize,
736
+ size_t NumJobs) {
737
+ size_t Remainder = NumJobs % PartitionSize;
738
+ size_t TargetSize = NumJobs / PartitionSize;
739
+ std::vector<size_t > PartitionIndex;
740
+ PartitionIndex.reserve (NumJobs);
741
+ for (size_t P = 0 ; P < PartitionSize; ++P) {
742
+ // Spread remainder evenly across partitions by adding 1 to the target
743
+ // size of the first Remainder of them.
744
+ size_t FillCount = TargetSize + ((P < Remainder) ? 1 : 0 );
745
+ std::fill_n (std::back_inserter (PartitionIndex), FillCount, P);
746
+ }
748
747
if (Comp.BatchSeed != 0 ) {
749
748
std::minstd_rand gen (Comp.BatchSeed );
750
- std::shuffle (Batchable .begin (), Batchable .end (), gen);
749
+ std::shuffle (PartitionIndex .begin (), PartitionIndex .end (), gen);
751
750
}
751
+ assert (PartitionIndex.size () == NumJobs);
752
+ return PartitionIndex;
752
753
}
753
754
754
755
// / Create \c NumberOfParallelCommands batches and assign each job to a
@@ -762,28 +763,28 @@ namespace driver {
762
763
}
763
764
764
765
assert (!Partition.empty ());
765
- maybeShuffleBatchable (Batchable);
766
-
767
- size_t i = 0 ;
766
+ auto PartitionIndex = assignJobsToPartitions (Partition. size (),
767
+ Batchable. size ());
768
+ assert (PartitionIndex. size () == Batchable. size ()) ;
768
769
auto const &TC = Comp.getToolChain ();
769
- for (const Job *Cmd : Batchable ) {
770
- maybeAdvanceToNextPartition (i, Partition, Batchable .size ());
771
- std::vector<const Job*> &P = Partition[i ];
772
- if (P.empty () || TC.jobsAreBatchCombinable (Comp, P[0 ], Cmd)) {
773
- if (Comp.ShowJobLifecycle )
774
- llvm::outs () << " Adding " << LogJob (Cmd)
775
- << " to batch " << i << ' \n ' ;
776
- P.push_back (Cmd);
777
- } else {
778
- // Strange but theoretically possible that we have a batchable job
779
- // that's not combinable with others; tack a new batch on for it.
780
- if (Comp.ShowJobLifecycle )
781
- llvm::outs () << " Adding " << LogJob (Cmd)
782
- << " to new batch " << Partition.size () << ' \n ' ;
783
- Partition.push_back (std::vector<const Job*>());
784
- Partition.back ().push_back (Cmd);
785
- }
786
- }
770
+ for_each (Batchable, PartitionIndex, [&] (const Job *Cmd, size_t Idx ) {
771
+ assert (Idx < Partition .size ());
772
+ std::vector<const Job*> &P = Partition[Idx ];
773
+ if (P.empty () || TC.jobsAreBatchCombinable (Comp, P[0 ], Cmd)) {
774
+ if (Comp.ShowJobLifecycle )
775
+ llvm::outs () << " Adding " << LogJob (Cmd)
776
+ << " to batch " << Idx << ' \n ' ;
777
+ P.push_back (Cmd);
778
+ } else {
779
+ // Strange but theoretically possible that we have a batchable job
780
+ // that's not combinable with others; tack a new batch on for it.
781
+ if (Comp.ShowJobLifecycle )
782
+ llvm::outs () << " Adding " << LogJob (Cmd)
783
+ << " to new batch " << Partition.size () << ' \n ' ;
784
+ Partition.push_back (std::vector<const Job*>());
785
+ Partition.back ().push_back (Cmd);
786
+ }
787
+ });
787
788
}
788
789
789
790
// FIXME: at the moment we're not passing OutputFileMaps to frontends, so
0 commit comments