Skip to content

Commit a5f237f

Browse files
authored
[MCA] Optimize memory consumption in resource pressure view (NFC) (llvm#124904)
ResourceUsage is a very sparse table. On large input asm sequences it consumes a lot of memory utilizing only a few percents of it (~4% on my benchmark). Reorganization of ResourceUsage to keep only used fields allows saving up to 18% of total memory use by mca or ~850% of input file size (~1.1GB in absolute values in my case).
1 parent 95e19e2 commit a5f237f

File tree

2 files changed

+62
-20
lines changed

2 files changed

+62
-20
lines changed

llvm/tools/llvm-mca/Views/ResourcePressureView.cpp

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,16 @@ ResourcePressureView::ResourcePressureView(const llvm::MCSubtargetInfo &sti,
3737
}
3838

3939
NumResourceUnits = R2VIndex;
40-
ResourceUsage.resize(NumResourceUnits * (getSource().size() + 1));
41-
std::fill(ResourceUsage.begin(), ResourceUsage.end(), 0.0);
40+
ResourceUsage.resize(getSource().size());
41+
42+
ResourceReleaseAtCycles InitValue{0, 0};
43+
auto Generator = [&InitValue]() {
44+
ResourceReleaseAtCycles Old = InitValue;
45+
++InitValue.ResourceIdx;
46+
return Old;
47+
};
48+
std::generate_n(std::back_inserter(CommonResourceUsage), NumResourceUnits,
49+
Generator);
4250
}
4351

4452
void ResourcePressureView::onEvent(const HWInstructionEvent &Event) {
@@ -60,8 +68,19 @@ void ResourcePressureView::onEvent(const HWInstructionEvent &Event) {
6068
assert(Resource2VecIndex.contains(RR.first));
6169
unsigned R2VIndex = Resource2VecIndex[RR.first];
6270
R2VIndex += llvm::countr_zero(RR.second);
63-
ResourceUsage[R2VIndex + NumResourceUnits * SourceIdx] += Use.second;
64-
ResourceUsage[R2VIndex + NumResourceUnits * Source.size()] += Use.second;
71+
72+
InstResourceUsage &RU = ResourceUsage[SourceIdx];
73+
ResourceReleaseAtCycles NewUsage{R2VIndex, Use.second};
74+
auto ResCyclesIt =
75+
lower_bound(RU, NewUsage, [](const auto &L, const auto &R) {
76+
return L.ResourceIdx < R.ResourceIdx;
77+
});
78+
if (ResCyclesIt != RU.end() && ResCyclesIt->ResourceIdx == R2VIndex)
79+
ResCyclesIt->Cycles += NewUsage.Cycles;
80+
else
81+
RU.insert(ResCyclesIt, std::move(NewUsage));
82+
83+
CommonResourceUsage[R2VIndex].Cycles += NewUsage.Cycles;
6584
}
6685
}
6786

@@ -135,10 +154,17 @@ void ResourcePressureView::printResourcePressurePerIter(raw_ostream &OS) const {
135154

136155
ArrayRef<llvm::MCInst> Source = getSource();
137156
const unsigned Executions = LastInstructionIdx / Source.size() + 1;
157+
auto UsageEntryEnd = CommonResourceUsage.end();
158+
auto UsageEntryIt = CommonResourceUsage.begin();
138159
for (unsigned I = 0, E = NumResourceUnits; I < E; ++I) {
139-
double Usage = ResourceUsage[I + Source.size() * E];
140-
printResourcePressure(FOS, Usage / Executions, (I + 1) * 7);
160+
double Pressure = 0.0;
161+
if (UsageEntryIt != UsageEntryEnd && UsageEntryIt->ResourceIdx == I) {
162+
Pressure = UsageEntryIt->Cycles / Executions;
163+
++UsageEntryIt;
164+
}
165+
printResourcePressure(FOS, Pressure, (I + 1) * 7);
141166
}
167+
assert(UsageEntryIt == UsageEntryEnd);
142168

143169
FOS.flush();
144170
OS << Buffer;
@@ -157,11 +183,17 @@ void ResourcePressureView::printResourcePressurePerInst(raw_ostream &OS) const {
157183
ArrayRef<llvm::MCInst> Source = getSource();
158184
const unsigned Executions = LastInstructionIdx / Source.size() + 1;
159185
for (const MCInst &MCI : Source) {
160-
unsigned BaseEltIdx = InstrIndex * NumResourceUnits;
186+
auto UsageEntryEnd = ResourceUsage[InstrIndex].end();
187+
auto UsageEntryIt = ResourceUsage[InstrIndex].begin();
161188
for (unsigned J = 0; J < NumResourceUnits; ++J) {
162-
double Usage = ResourceUsage[J + BaseEltIdx];
163-
printResourcePressure(FOS, Usage / Executions, (J + 1) * 7);
189+
double Pressure = 0.0;
190+
if (UsageEntryIt != UsageEntryEnd && UsageEntryIt->ResourceIdx == J) {
191+
Pressure = UsageEntryIt->Cycles / Executions;
192+
++UsageEntryIt;
193+
}
194+
printResourcePressure(FOS, Pressure, (J + 1) * 7);
164195
}
196+
assert(UsageEntryIt == UsageEntryEnd);
165197

166198
FOS << printInstructionString(MCI) << '\n';
167199
FOS.flush();
@@ -180,17 +212,22 @@ json::Value ResourcePressureView::toJSON() const {
180212
// non-zero values.
181213
ArrayRef<llvm::MCInst> Source = getSource();
182214
const unsigned Executions = LastInstructionIdx / Source.size() + 1;
183-
for (const auto &R : enumerate(ResourceUsage)) {
184-
const ReleaseAtCycles &RU = R.value();
185-
if (RU.getNumerator() == 0)
186-
continue;
187-
unsigned InstructionIndex = R.index() / NumResourceUnits;
188-
unsigned ResourceIndex = R.index() % NumResourceUnits;
189-
double Usage = RU / Executions;
215+
216+
auto AddToJSON = [&ResourcePressureInfo, Executions](
217+
const ResourceReleaseAtCycles &RU, unsigned InstIndex) {
218+
assert(RU.Cycles.getNumerator() != 0);
219+
double Usage = RU.Cycles / Executions;
190220
ResourcePressureInfo.push_back(
191-
json::Object({{"InstructionIndex", InstructionIndex},
192-
{"ResourceIndex", ResourceIndex},
221+
json::Object({{"InstructionIndex", InstIndex},
222+
{"ResourceIndex", RU.ResourceIdx},
193223
{"ResourceUsage", Usage}}));
224+
};
225+
for (const auto &[InstIndex, Usages] : enumerate(ResourceUsage))
226+
for (const auto &RU : Usages)
227+
AddToJSON(RU, InstIndex);
228+
for (const auto &RU : CommonResourceUsage) {
229+
if (RU.Cycles.getNumerator() != 0)
230+
AddToJSON(RU, Source.size());
194231
}
195232

196233
json::Object JO({{"ResourcePressureInfo", std::move(ResourcePressureInfo)}});

llvm/tools/llvm-mca/Views/ResourcePressureView.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,13 @@ class ResourcePressureView : public InstructionView {
7777
// resource ID.
7878
llvm::DenseMap<unsigned, unsigned> Resource2VecIndex;
7979

80-
// Table of resources used by instructions.
81-
std::vector<ReleaseAtCycles> ResourceUsage;
80+
struct ResourceReleaseAtCycles {
81+
unsigned ResourceIdx;
82+
ReleaseAtCycles Cycles;
83+
};
84+
using InstResourceUsage = std::vector<ResourceReleaseAtCycles>;
85+
std::vector<InstResourceUsage> ResourceUsage;
86+
InstResourceUsage CommonResourceUsage;
8287
unsigned NumResourceUnits;
8388

8489
void printResourcePressurePerIter(llvm::raw_ostream &OS) const;

0 commit comments

Comments
 (0)