Skip to content

Commit 6b6ea67

Browse files
committed
Refactor HPLinpack profiles to be separated by vendor performance libraries.
1 parent 4fddd32 commit 6b6ea67

6 files changed

Lines changed: 408 additions & 241 deletions

File tree

src/VirtualClient/VirtualClient.Actions.UnitTests/HPLinpack/HPLinpackExecutorTests.cs

Lines changed: 79 additions & 130 deletions
Large diffs are not rendered by default.

src/VirtualClient/VirtualClient.Actions/HPLinpack/HPLinpackExecutor.cs

Lines changed: 61 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@ namespace VirtualClient.Actions
1010
using System.Threading;
1111
using System.Threading.Tasks;
1212
using Microsoft.Extensions.DependencyInjection;
13-
using Microsoft.Extensions.Logging;
1413
using VirtualClient.Common;
1514
using VirtualClient.Common.Extensions;
16-
using VirtualClient.Common.Platform;
1715
using VirtualClient.Common.Telemetry;
1816
using VirtualClient.Contracts;
1917
using VirtualClient.Contracts.Metadata;
@@ -120,11 +118,11 @@ public string CCFlags
120118
/// <summary>
121119
/// The name of the package where the ARMPerformanceLibraries package is downloaded.
122120
/// </summary>
123-
public string PerformanceLibrariesPackageName
121+
public string PerformanceLibraryPackageName
124122
{
125123
get
126124
{
127-
return this.Parameters.GetValue<string>(nameof(this.PerformanceLibrariesPackageName), "hplperformancelibraries");
125+
return this.Parameters.GetValue<string>(nameof(this.PerformanceLibraryPackageName), "hplperformancelibraries");
128126
}
129127
}
130128

@@ -166,7 +164,12 @@ public string PerformanceLibraryVersion
166164
/// <summary>
167165
/// The path to the HPL directory.
168166
/// </summary>
169-
protected string HPLDirectory { get; set; }
167+
protected string HPLinpackPackagePath { get; set; }
168+
169+
/// <summary>
170+
/// The path to the HPL performance library package.
171+
/// </summary>
172+
protected string PerformanceLibraryPackagePath { get; set; }
170173

171174
/// <summary>
172175
/// The number of Process rows(P).
@@ -183,7 +186,6 @@ public string PerformanceLibraryVersion
183186
/// </summary>
184187
protected override async Task InitializeAsync(EventContext telemetryContext, CancellationToken cancellationToken)
185188
{
186-
await this.EvaluateParametersAsync(cancellationToken);
187189
this.coreCount = this.cpuInfo.LogicalProcessorCount;
188190

189191
MemoryInfo memoryInfo = await this.systemManagement.GetMemoryInfoAsync(CancellationToken.None);
@@ -192,25 +194,31 @@ protected override async Task InitializeAsync(EventContext telemetryContext, Can
192194
this.ValidateParameters();
193195

194196
DependencyPath workloadPackage = await this.GetPlatformSpecificPackageAsync(this.PackageName, cancellationToken);
195-
this.HPLDirectory = workloadPackage.Path;
197+
this.HPLinpackPackagePath = workloadPackage.Path;
196198

197-
DependencyPath performanceLibrariesPackage = await this.packageManager.GetPackageAsync(this.PerformanceLibrariesPackageName, cancellationToken)
198-
.ConfigureAwait(false);
199+
await this.MakeFilesExecutableAsync(this.HPLinpackPackagePath, this.Platform, cancellationToken);
199200

200-
await this.ConfigurePerformanceLibrary(telemetryContext, cancellationToken);
201+
if (!string.IsNullOrWhiteSpace(this.PerformanceLibrary))
202+
{
203+
DependencyPath performanceLibrariesPackage = await this.packageManager.GetPackageAsync(this.PerformanceLibraryPackageName, cancellationToken);
204+
this.PerformanceLibraryPackagePath = performanceLibrariesPackage.Path;
205+
206+
await this.MakeFilesExecutableAsync(this.PerformanceLibraryPackagePath, this.Platform, cancellationToken);
207+
await this.ConfigurePerformanceLibrary(telemetryContext, cancellationToken);
208+
}
201209

202210
if (this.CpuArchitecture == Architecture.X64 && this.PerformanceLibrary == "INTEL")
203211
{
204212
// Use PlatformSpecifics.Combine for paths instead of string concatenation
205213
if (this.PerformanceLibraryVersion == "2024.2.2.17")
206214
{
207215
string intelMklPath = "/opt/intel/oneapi/mkl/2024.2/share/mkl/benchmarks/mp_linpack";
208-
await this.ExecuteCommandAsync("cp", $"-r {intelMklPath} {this.intelPerfLibrariesPath}", this.HPLDirectory, telemetryContext, cancellationToken);
216+
await this.ExecuteCommandAsync("cp", $"-r {intelMklPath} {this.intelPerfLibrariesPath}", this.HPLinpackPackagePath, telemetryContext, cancellationToken);
209217
}
210218
else if (this.PerformanceLibraryVersion == "2025.1.0.803")
211219
{
212220
string intelMklPath = "~/intel/oneapi/mkl/2025.1/share/mkl/benchmarks/mp_linpack";
213-
await this.ExecuteCommandAsync("cp", $"-r {intelMklPath} {this.intelPerfLibrariesPath}", this.HPLDirectory, telemetryContext, cancellationToken);
221+
await this.ExecuteCommandAsync("cp", $"-r {intelMklPath} {this.intelPerfLibrariesPath}", this.HPLinpackPackagePath, telemetryContext, cancellationToken);
214222
}
215223
else
216224
{
@@ -219,11 +227,11 @@ protected override async Task InitializeAsync(EventContext telemetryContext, Can
219227
}
220228
else
221229
{
222-
await this.DeleteFileAsync(this.PlatformSpecifics.Combine(this.HPLDirectory, this.makeFileName));
223-
await this.DeleteFileAsync(this.PlatformSpecifics.Combine(this.HPLDirectory, "setup", this.makeFileName));
224-
await this.ExecuteCommandAsync("bash", "-c \"source make_generic\"", this.PlatformSpecifics.Combine(this.HPLDirectory, "setup"), telemetryContext, cancellationToken, runElevated: true);
230+
await this.DeleteFileAsync(this.Combine(this.HPLinpackPackagePath, this.makeFileName));
231+
await this.DeleteFileAsync(this.Combine(this.HPLinpackPackagePath, "setup", this.makeFileName));
232+
await this.ExecuteCommandAsync("bash", "-c \"source make_generic\"", this.Combine(this.HPLinpackPackagePath, "setup"), telemetryContext, cancellationToken, runElevated: true);
225233
await this.ConfigureMakeFileAsync(telemetryContext, cancellationToken);
226-
await this.ExecuteCommandAsync("ln", $"-s {this.PlatformSpecifics.Combine(this.HPLDirectory, "setup", this.makeFileName)} {this.makeFileName}", this.HPLDirectory, telemetryContext, cancellationToken);
234+
await this.ExecuteCommandAsync("ln", $"-s {this.Combine(this.HPLinpackPackagePath, "setup", this.makeFileName)} {this.makeFileName}", this.HPLinpackPackagePath, telemetryContext, cancellationToken);
227235
}
228236
}
229237

@@ -235,16 +243,21 @@ protected override async Task ExecuteAsync(EventContext telemetryContext, Cancel
235243
using (BackgroundOperations profiling = BackgroundOperations.BeginProfiling(this, cancellationToken))
236244
{
237245
DateTime startTime = DateTime.UtcNow;
238-
await this.ExecuteCommandAsync("make", $"arch=Linux_GCC", this.HPLDirectory, telemetryContext, cancellationToken)
239-
.ConfigureAwait(false);
240-
241-
await this.ConfigureDatFileAsync(telemetryContext, cancellationToken).ConfigureAwait(false);
242-
IProcessProxy process;
246+
await this.ExecuteCommandAsync("make", $"arch=Linux_GCC", this.HPLinpackPackagePath, telemetryContext, cancellationToken);
247+
await this.ConfigureDatFileAsync(telemetryContext, cancellationToken);
248+
IProcessProxy process = null;
243249

244250
if (this.CpuArchitecture == Architecture.X64 && this.PerformanceLibrary == "INTEL")
245251
{
246252
this.commandArguments = "./runme_intel64_dynamic";
247-
process = await this.ExecuteCommandAsync("bash", $"-c \". /opt/intel/oneapi/mpi/latest/env/vars.sh && {this.commandArguments}\"", this.PlatformSpecifics.Combine(this.intelPerfLibrariesPath, "mp_linpack"), telemetryContext, cancellationToken, runElevated: true);
253+
254+
process = await this.ExecuteCommandAsync(
255+
"bash",
256+
$"-c \". /opt/intel/oneapi/mpi/latest/env/vars.sh && {this.commandArguments}\"",
257+
this.Combine(this.intelPerfLibrariesPath, "mp_linpack"),
258+
telemetryContext,
259+
cancellationToken,
260+
runElevated: true);
248261
}
249262
else
250263
{
@@ -262,15 +275,20 @@ await this.ExecuteCommandAsync("make", $"arch=Linux_GCC", this.HPLDirectory, tel
262275
this.commandArguments += $" --bind-to core";
263276
}
264277

265-
process = await this.ExecuteCommandAsync("runuser", $"-u {Environment.UserName} -- mpirun {this.commandArguments} ./xhpl", this.PlatformSpecifics.Combine(this.HPLDirectory, "bin", "Linux_GCC"), telemetryContext, cancellationToken, runElevated: true);
278+
process = await this.ExecuteCommandAsync(
279+
"runuser",
280+
$"-u {Environment.UserName} -- mpirun {this.commandArguments} ./xhpl",
281+
this.Combine(this.HPLinpackPackagePath, "bin", "Linux_GCC"),
282+
telemetryContext,
283+
cancellationToken,
284+
runElevated: true);
266285
}
267286

268287
using (process)
269288
{
270289
if (!cancellationToken.IsCancellationRequested)
271290
{
272-
await this.LogProcessDetailsAsync(process, telemetryContext, "HPLinpack", logToFile: true)
273-
.ConfigureAwait();
291+
await this.LogProcessDetailsAsync(process, telemetryContext, "HPLinpack");
274292

275293
process.ThrowIfErrored<WorkloadException>(errorReason: ErrorReason.WorkloadFailed);
276294
this.CaptureMetrics(process.StandardOutput.ToString(), $"{this.commandArguments}", startTime, DateTime.UtcNow, telemetryContext, cancellationToken);
@@ -303,16 +321,14 @@ private void ValidateParameters()
303321
{
304322
if (this.cpuInfo.IsHyperthreadingEnabled && this.NumberOfProcesses > this.coreCount)
305323
{
306-
throw new Exception(
307-
$"NumberOfProcesses parameter value should be less than or equal to number of logical cores");
324+
throw new WorkloadException(
325+
$"The '{nameof(this.NumberOfProcesses)}' parameter value should be less than or equal to number of logical processors on the system.",
326+
ErrorReason.InvalidProfileDefinition);
308327
}
309328
}
310329

311330
private async Task ConfigurePerformanceLibrary(EventContext telemetryContext, CancellationToken cancellationToken)
312331
{
313-
DependencyPath performanceLibrariesPackage = await this.packageManager.GetPackageAsync(this.PerformanceLibrariesPackageName, cancellationToken)
314-
.ConfigureAwait(false);
315-
316332
if (this.CpuArchitecture == Architecture.Arm64 && this.PerformanceLibrary == "ARM")
317333
{
318334
// Switch between ARM perf lib versions
@@ -331,8 +347,7 @@ private async Task ConfigurePerformanceLibrary(EventContext telemetryContext, Ca
331347
throw new WorkloadException($"The HPL workload currently only supports versions 23.04.1, 24.10 and 25.04.1 of the ARM performance libraries");
332348
}
333349

334-
this.armPerfLibrariesPath = this.PlatformSpecifics.Combine(performanceLibrariesPackage.Path, "ARM");
335-
await this.systemManagement.MakeFileExecutableAsync(this.PlatformSpecifics.Combine(this.armPerfLibrariesPath, $"{this.hplArmPerfLibrary}"), this.Platform, cancellationToken).ConfigureAwait(false);
350+
this.armPerfLibrariesPath = this.Combine(this.PerformanceLibraryPackagePath, "linux-arm64");
336351
await this.ExecuteCommandAsync($"./{this.hplArmPerfLibrary}", $"-a", this.armPerfLibrariesPath, telemetryContext, cancellationToken, runElevated: true);
337352
}
338353

@@ -345,15 +360,13 @@ private async Task ConfigurePerformanceLibrary(EventContext telemetryContext, Ca
345360
case "4.2.0":
346361
case "5.0.0":
347362
case "5.1.0":
348-
this.amdPerfLibrariesPath = this.PlatformSpecifics.Combine(performanceLibrariesPackage.Path, "AMD", this.PerformanceLibraryVersion);
363+
this.amdPerfLibrariesPath = this.Combine(this.PerformanceLibraryPackagePath, "linux-x64");
349364
break;
350365
default:
351366
throw new WorkloadException($"The HPL workload currently only supports 4.2.0, 5.0.0 and 5.1.0 versions of AMD performance libraries");
352367
}
353368

354-
string installPath = this.PlatformSpecifics.Combine(this.HPLDirectory);
355-
await this.systemManagement.MakeFileExecutableAsync(this.PlatformSpecifics.Combine(this.amdPerfLibrariesPath, "install.sh"), this.Platform, cancellationToken).ConfigureAwait(false);
356-
await this.ExecuteCommandAsync($"./install.sh", $"-t {installPath} -i lp64", this.amdPerfLibrariesPath, telemetryContext, cancellationToken, runElevated: true).ConfigureAwait(false);
369+
await this.ExecuteCommandAsync($"./install.sh", $"-t {this.HPLinpackPackagePath} -i lp64", this.amdPerfLibrariesPath, telemetryContext, cancellationToken, runElevated: true);
357370
}
358371

359372
if (this.PerformanceLibrary == "INTEL")
@@ -373,25 +386,24 @@ private async Task ConfigurePerformanceLibrary(EventContext telemetryContext, Ca
373386
throw new WorkloadException($"The HPL workload currently only supports 2024.2.2.17 and 2025.1.0.803 versions of INTEL Math Kernel Library");
374387
}
375388

376-
this.intelPerfLibrariesPath = this.PlatformSpecifics.Combine(performanceLibrariesPackage.Path, "INTEL", this.PerformanceLibraryVersion);
377-
await this.systemManagement.MakeFileExecutableAsync(this.PlatformSpecifics.Combine(this.intelPerfLibrariesPath, $"{this.hplIntelHpcToolkit}"), this.Platform, cancellationToken).ConfigureAwait(false);
378-
await this.ExecuteCommandAsync($"./{this.hplIntelHpcToolkit}", "-a --silent --eula accept", this.intelPerfLibrariesPath, telemetryContext, cancellationToken, runElevated: true);
379-
await this.systemManagement.MakeFileExecutableAsync(this.PlatformSpecifics.Combine(this.intelPerfLibrariesPath, $"{this.hplIntelMKL}"), this.Platform, cancellationToken).ConfigureAwait(false);
389+
this.intelPerfLibrariesPath = this.Combine(this.PerformanceLibraryPackagePath, "linux-x64");
390+
380391
await this.ExecuteCommandAsync($"./{this.hplIntelMKL}", "-a --silent --eula accept", this.intelPerfLibrariesPath, telemetryContext, cancellationToken, runElevated: true);
392+
await this.ExecuteCommandAsync($"./{this.hplIntelHpcToolkit}", "-a --silent --eula accept", this.intelPerfLibrariesPath, telemetryContext, cancellationToken, runElevated: true);
381393
}
382394
}
383395
}
384396

385397
private async Task ConfigureMakeFileAsync(EventContext telemetryContext, CancellationToken cancellationToken)
386398
{
387-
string makeFilePath = this.PlatformSpecifics.Combine(this.HPLDirectory, "setup", this.makeFileName);
388-
await this.ExecuteCommandAsync("mv", $"Make.UNKNOWN {this.makeFileName}", this.PlatformSpecifics.Combine(this.HPLDirectory, $"setup"), telemetryContext, cancellationToken);
399+
string makeFilePath = this.Combine(this.HPLinpackPackagePath, "setup", this.makeFileName);
400+
await this.ExecuteCommandAsync("mv", $"Make.UNKNOWN {this.makeFileName}", this.Combine(this.HPLinpackPackagePath, $"setup"), telemetryContext, cancellationToken);
389401

390402
await this.fileSystem.File.ReplaceInFileAsync(
391403
makeFilePath, @"ARCH *= *[^\n]*", "ARCH = Linux_GCC", cancellationToken);
392404

393405
await this.fileSystem.File.ReplaceInFileAsync(
394-
makeFilePath, @"TOPdir *= *[^\n]*", $"TOPdir = {this.HPLDirectory}", cancellationToken);
406+
makeFilePath, @"TOPdir *= *[^\n]*", $"TOPdir = {this.HPLinpackPackagePath}", cancellationToken);
395407

396408
await this.fileSystem.File.ReplaceInFileAsync(
397409
makeFilePath, @"CCFLAGS *= *[^\n]*", $"CCFLAGS = $(HPL_DEFS) {this.CCFlags}", cancellationToken);
@@ -434,10 +446,10 @@ await this.fileSystem.File.ReplaceInFileAsync(
434446
else if (this.PerformanceLibrary == "AMD" && this.CpuArchitecture == Architecture.X64)
435447
{
436448
await this.fileSystem.File.ReplaceInFileAsync(
437-
makeFilePath, @"LAdir *=", $"LAdir = {this.PlatformSpecifics.Combine(this.HPLDirectory, this.PerformanceLibraryVersion, "gcc")}", cancellationToken);
449+
makeFilePath, @"LAdir *=", $"LAdir = {this.Combine(this.HPLinpackPackagePath, this.PerformanceLibraryVersion, "gcc")}", cancellationToken);
438450

439451
await this.fileSystem.File.ReplaceInFileAsync(
440-
makeFilePath, @"LAlib *= *[^\n]*", $"LAlib = {this.PlatformSpecifics.Combine(this.HPLDirectory, this.PerformanceLibraryVersion, "gcc", "lib", "libblis.a")}", cancellationToken);
452+
makeFilePath, @"LAlib *= *[^\n]*", $"LAlib = {this.Combine(this.HPLinpackPackagePath, this.PerformanceLibraryVersion, "gcc", "lib", "libblis.a")}", cancellationToken);
441453
}
442454
else
443455
{
@@ -468,9 +480,9 @@ private async Task ConfigureDatFileAsync(EventContext telemetryContext, Cancella
468480
if (this.CpuArchitecture == Architecture.X64 && this.PerformanceLibrary == "INTEL")
469481
{
470482
this.SetParameters(this.cpuInfo.SocketCount);
471-
hplDatFile = this.PlatformSpecifics.Combine(this.intelPerfLibrariesPath, "mp_linpack", "HPL.dat");
483+
hplDatFile = this.Combine(this.intelPerfLibrariesPath, "mp_linpack", "HPL.dat");
472484

473-
string hplRunmeFile = this.PlatformSpecifics.Combine(this.intelPerfLibrariesPath, "mp_linpack", "runme_intel64_dynamic");
485+
string hplRunmeFile = this.Combine(this.intelPerfLibrariesPath, "mp_linpack", "runme_intel64_dynamic");
474486
await this.fileSystem.File.ReplaceInFileAsync(
475487
hplRunmeFile, @"export MPI_PROC_NUM *= *[^\n]*", $"export MPI_PROC_NUM={this.cpuInfo.SocketCount}", cancellationToken);
476488

@@ -482,7 +494,7 @@ await this.fileSystem.File.ReplaceInFileAsync(
482494
}
483495
else
484496
{
485-
hplDatFile = this.PlatformSpecifics.Combine(this.HPLDirectory, "bin", "Linux_GCC", "HPL.dat");
497+
hplDatFile = this.Combine(this.HPLinpackPackagePath, "bin", "Linux_GCC", "HPL.dat");
486498
this.SetParameters(this.NumberOfProcesses);
487499
}
488500

@@ -536,8 +548,7 @@ private async Task DeleteFileAsync(string filePath)
536548
{
537549
if (this.systemManagement.FileSystem.File.Exists(filePath))
538550
{
539-
await this.systemManagement.FileSystem.File.DeleteAsync(filePath)
540-
.ConfigureAwait(false);
551+
await this.systemManagement.FileSystem.File.DeleteAsync(filePath);
541552
}
542553
}
543554

0 commit comments

Comments
 (0)