Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/VirtualClient/TestResources/Results_StreamMsft.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Read and write vector size is 64.0 MB
Scale and Copy vector size is 128.0 MB
Triad and Add vector size is 192.0 MB
Test executed with 1 cores
Latency Array size is 32.000 MB per core so total size is 32.000 MB
Number of threads is 1
Loops are using NEON instructions
Number of latency threads is 1
Number of Iterations is 6
Number of Internal Iterations is 1 for BW
Number of Internal Iterations is 1 for Latency
Function Best Rate MB/s
Read: 144 141 140 113 110 114
Copy: 277 272 265 117 115 120
Scale: 275 270 268 118 117 119
Add: 419 412 407 115 114 116
Triad: 415 411 405 116 114 116
Write: 128 126 124 127 125 129
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace VirtualClient.Actions
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Moq;
using NUnit.Framework;
using VirtualClient;
using VirtualClient.Common;
using VirtualClient.Contracts;

[TestFixture]
[Category("Functional")]
public class StreamProfileTests
{
private DependencyFixture mockFixture;

[OneTimeSetUp]
public void SetupFixture()
{
this.mockFixture = new DependencyFixture();
ComponentTypeCache.Instance.LoadComponentTypes(TestDependencies.TestDirectory);
}

[Test]
[TestCase("PERF-MEM-STREAMTRIAD.json")]
public void StreamTriadWorkloadProfileParametersAreInlinedCorrectly(string profile)
{
this.mockFixture.Setup(PlatformID.Unix);
using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.mockFixture.Dependencies))
{
WorkloadAssert.ParameterReferencesInlined(executor.Profile);
}
}

[Test]
[TestCase("PERF-MEM-STREAMTRIAD.json")]
public async Task StreamTriadWorkloadProfileExecutesTheExpectedWorkloadsOnUnixPlatform(string profile)
{
IEnumerable<string> expectedCommands = StreamProfileTests.GetStreamTriadProfileExpectedCommands();

// Setup the expectations for the workload
// - Workload package is installed and exists.
// - The workload generates valid results.
this.mockFixture.Setup(PlatformID.Unix);
this.mockFixture.SystemManagement.Setup(mgr => mgr.GetCpuInfoAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(new CpuInfo("Name", "Description", 1, 2, 1, 1, true));

this.mockFixture.SetupPackage("stream", expectedFiles: "linux-x64/stream");

this.mockFixture.ProcessManager.OnCreateProcess = (command, arguments, workingDir) =>
{
IProcessProxy process = this.mockFixture.CreateProcess(command, arguments, workingDir);
if (arguments.Contains("Stream", StringComparison.OrdinalIgnoreCase))
{
process.StandardOutput.Append(TestDependencies.GetResourceFileContents("Results_Stream.txt"));
}
else if (arguments.Contains("lscpu | grep 'Flags'"))
{
process.StandardOutput.AppendLine("Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves avx512vbmi");
}

return process;
};

using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.mockFixture.Dependencies))
{
executor.ExecuteDependencies = false;
await executor.ExecuteAsync(ProfileTiming.OneIteration(), CancellationToken.None).ConfigureAwait(false);
await executor.ExecuteAsync(ProfileTiming.OneIteration(), CancellationToken.None).ConfigureAwait(false);

WorkloadAssert.CommandsExecuted(this.mockFixture, expectedCommands.ToArray());
}
}

[Test]
[Ignore("We need to rethink how to do dependency testing with extension model.")]
[TestCase("PERF-MEM-STREAMTRIAD.json")]
public async Task StreamTriadWorkloadProfileInstallsTheExpectedDependenciesOnUnixPlatform(string profile)
{
// The setup in a typical Azure VM scenario
this.mockFixture.Setup(PlatformID.Unix);

using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.mockFixture.Dependencies, dependenciesOnly: true))
{
executor.ExecuteDependencies = false;
await executor.ExecuteAsync(ProfileTiming.OneIteration(), CancellationToken.None).ConfigureAwait(false);

// Workload dependency package expectations
// The workload dependency package should have been installed at this point.
WorkloadAssert.WorkloadPackageInstalled(this.mockFixture, "stream");
}
}

[Test]
[TestCase("PERF-MEM-STREAMTRIAD.json")]
public void StreamTriadProfileActionsWillNotBeExecutedIfTheWorkloadPackageDoesNotExist(string profile)
{
this.mockFixture.Setup(PlatformID.Unix);
this.mockFixture.SystemManagement.Setup(mgr => mgr.GetCpuInfoAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(new CpuInfo("Name", "Description", 1, 2, 1, 1, true));

// We ensure the workload package does not exist.
this.mockFixture.PackageManager.Clear();

using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.mockFixture.Dependencies))
{
executor.ExecuteDependencies = false;

DependencyException error = Assert.ThrowsAsync<DependencyException>(() => executor.ExecuteAsync(ProfileTiming.OneIteration(), CancellationToken.None));
Assert.IsTrue(error.Reason == ErrorReason.WorkloadDependencyMissing);
}
}

[Test]
[TestCase("PERF-MEM-STREAMMSFT.json")]
public void StreamMsftWorkloadProfileParametersAreInlinedCorrectly(string profile)
{
this.mockFixture.Setup(PlatformID.Unix);
using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.mockFixture.Dependencies))
{
WorkloadAssert.ParameterReferencesInlined(executor.Profile);
}
}

[Test]
[TestCase("PERF-MEM-STREAMMSFT.json")]
public async Task StreamMsftWorkloadProfileExecutesTheExpectedWorkloadsOnUnixPlatform(string profile)
{
IEnumerable<string> expectedCommands = StreamProfileTests.GetStreamMsftProfileExpectedCommands();

// Setup the expectations for the workload
// - Workload package is installed and exists.
// - The workload generates valid results.
this.mockFixture.Setup(PlatformID.Unix, Architecture.Arm64);
this.mockFixture.SetupPackage("streammsft", expectedFiles: "linux-arm64/stream");

this.mockFixture.SystemManagement.Setup(mgr => mgr.GetCpuInfoAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(new CpuInfo("Name", "Description", 1, 2, 1, 1, true));

this.mockFixture.ProcessManager.OnCreateProcess = (command, arguments, workingDir) =>
{
IProcessProxy process = this.mockFixture.CreateProcess(command, arguments, workingDir);
if (arguments.Contains("perfrunner", StringComparison.OrdinalIgnoreCase))
{
process.StandardOutput.Append(TestDependencies.GetResourceFileContents("Results_StreamMsft.txt"));
}
else if (arguments.Contains("make", StringComparison.OrdinalIgnoreCase))
{
// Make command should succeed without output
}

return process;
};

using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.mockFixture.Dependencies))
{
executor.ExecuteDependencies = false;
await executor.ExecuteAsync(ProfileTiming.OneIteration(), CancellationToken.None).ConfigureAwait(false);

WorkloadAssert.CommandsExecuted(this.mockFixture, expectedCommands.ToArray());
}
}

[Test]
[TestCase("PERF-MEM-STREAM.json")]
public void StreamWorkloadProfileParametersAreInlinedCorrectly(string profile)
{
this.mockFixture.Setup(PlatformID.Unix);
using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.mockFixture.Dependencies))
{
WorkloadAssert.ParameterReferencesInlined(executor.Profile);
}
}

[Test]
[TestCase("PERF-MEM-STREAM.json")]
public async Task StreamWorkloadProfileExecutesTheExpectedWorkloadsOnUnixPlatform(string profile)
{
IEnumerable<string> expectedCommands = StreamProfileTests.GetStreamProfileExpectedCommands();

// Setup the expectations for the workload
// - Workload package is installed and exists.
// - The workload generates valid results.
this.mockFixture.Setup(PlatformID.Unix);
this.mockFixture.SetupPackage("stream", expectedFiles: "linux-x64/stream");
this.mockFixture.SystemManagement.Setup(mgr => mgr.GetCpuInfoAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(new CpuInfo("Name", "Description", 1, 2, 1, 1, true));

this.mockFixture.ProcessManager.OnCreateProcess = (command, arguments, workingDir) =>
{
IProcessProxy process = this.mockFixture.CreateProcess(command, arguments, workingDir);
if (arguments.Contains("streamworkload", StringComparison.OrdinalIgnoreCase))
{
process.StandardOutput.Append(TestDependencies.GetResourceFileContents("Results_Stream.txt"));
}
else if (arguments.Contains("gcc", StringComparison.OrdinalIgnoreCase))
{
// Compilation command - no output needed
}

return process;
};

using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.mockFixture.Dependencies))
{
executor.ExecuteDependencies = false;
await executor.ExecuteAsync(ProfileTiming.OneIteration(), CancellationToken.None).ConfigureAwait(false);

await executor.ExecuteAsync(ProfileTiming.OneIteration(), CancellationToken.None).ConfigureAwait(false);

WorkloadAssert.CommandsExecuted(this.mockFixture, expectedCommands.ToArray());
}
}

[Test]
[TestCase("PERF-MEM-STREAM.json")]
public void StreamProfileActionsWillNotBeExecutedIfTheWorkloadPackageDoesNotExist(string profile)
{
this.mockFixture.Setup(PlatformID.Unix);
this.mockFixture.SystemManagement.Setup(mgr => mgr.GetCpuInfoAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(new CpuInfo("Name", "Description", 1, 2, 1, 1, true));

// We ensure the workload package does not exist.
this.mockFixture.PackageManager.Clear();

this.mockFixture.ProcessManager.OnCreateProcess = (exe, arguments, workingDir) =>
{
IProcessProxy process = this.mockFixture.CreateProcess(exe, arguments, workingDir);
process.StandardOutput.AppendLine("gcc (Ubuntu 10.3.0-1ubuntu1~20.04) 10.3.0");
process.StandardOutput.AppendLine("cc (Ubuntu 10.3.0-1ubuntu1~20.04) 10.3.0");
return process;
};

using (ProfileExecutor executor = TestDependencies.CreateProfileExecutor(profile, this.mockFixture.Dependencies))
{
executor.ExecuteDependencies = false;

DependencyException error = Assert.ThrowsAsync<DependencyException>(() => executor.ExecuteAsync(ProfileTiming.OneIteration(), CancellationToken.None));
Assert.IsTrue(error.Reason == ErrorReason.WorkloadDependencyMissing);
}
}

private static IEnumerable<string> GetStreamTriadProfileExpectedCommands()
{
return new List<string>
{
"bash -c \"lscpu \\| grep 'Flags'\"",
"bash -c \"export KMP_AFFINITY=.*&& export OMP_NUM_THREADS=.*&& export LD_LIBRARY_PATH=.*&& chmod \\+x.*&&.*Stream.*\""
};
}

private static IEnumerable<string> GetStreamProfileExpectedCommands()
{
return new List<string>
{
"bash -c \"gcc.*stream\\.c.*-o.*streamworkload.*\"",
"bash -c \"export OMP_NUM_THREADS=.*&&.*chmod.*\\+x.*streamworkload.*&&.*streamworkload.*\"",
};
}

private static IEnumerable<string> GetStreamMsftProfileExpectedCommands()
{
return new List<string>
{
"bash.*make",
"bash.*perfrunner.*--threads.*--internal-iter",
};
}

private static IEnumerable<string> GetStreamWindowsProfileExpectedCommands()
{
return new List<string>
{
"cmd\\.exe.*stream\\.exe.*-n 50.*-s 320000000",
};
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
-------------------------------------------------------------
STREAM version $Revision: 5.10 $
-------------------------------------------------------------
This system uses 8 bytes per array element.
-------------------------------------------------------------
Array size = 268435456 (elements), Offset = 0 (elements)
Memory per array = 2048.0 MiB (= 2.0 GiB).
Total memory required = 6144.0 MiB (= 6.0 GiB).
Each kernel will be executed 100 times.
The *best* time for each kernel (excluding the first iteration)
will be used to compute the reported bandwidth.
-------------------------------------------------------------
Number of Threads requested = 4
Number of Threads counted = 4
-------------------------------------------------------------
Your clock granularity/precision appears to be 1 microseconds.
Each test below will take on the order of 161936 microseconds.
(= 161936 clock ticks)
Increase the size of the arrays if this shows that
you are not getting at least 20 clock ticks per test.
-------------------------------------------------------------
WARNING -- The above is only a rough guideline.
For best results, please be sure you know the
precision of your system timer.
-------------------------------------------------------------
Function Best Rate MB/s Avg time Min time Max time
Copy: 18514.5 0.242368 0.231979 0.317779
Scale: 18333.8 0.244441 0.234265 0.356043
Add: 23043.7 0.293571 0.279575 0.377037
Triad: 23314.0 0.291828 0.276334 0.337149
-------------------------------------------------------------
Solution Validates: avg error less than 1.000000e-13 on all three arrays
-------------------------------------------------------------
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
-------------------------------------------------------------
STREAM version $Revision: 5.10 $
-------------------------------------------------------------
This system uses 8 bytes per array element.
-------------------------------------------------------------
Array size = 320000000 (elements), Offset = 0 (elements)
Memory per array = 2441.4 MiB (= 2.4 GiB).
Total memory required = 7324.2 MiB (= 7.2 GiB).
Each kernel will be executed 50 times.
The *best* time for each kernel (excluding the first iteration)
will be used to compute the reported bandwidth.
-------------------------------------------------------------
Number of Threads requested = 8
Number of Threads counted = 8
-------------------------------------------------------------
Your clock granularity/precision appears to be 100 nanoseconds.
Each test below will take on the order of 29879 microseconds.
(= 298790 clock ticks)
Increase the size of the arrays if this shows that
you are not getting at least 20 clock ticks per test.
-------------------------------------------------------------
WARNING -- The above is only a rough guideline.
For best results, please be sure you know the
precision of your system timer.
-------------------------------------------------------------
| Function | Avg (MB/s) | Best (MB/s) | Worst (MB/s) | Avg time | Min time | Max time |
|----------|------------|-------------|--------------|----------|----------|----------|
| Copy | 42156.3 | 42890.7 | 41234.5 | 0.122345 | 0.119876 | 0.124567 |
| Scale | 41987.2 | 42678.9 | 41098.3 | 0.123456 | 0.120987 | 0.125678 |
| Add | 43521.8 | 44234.6 | 42765.4 | 0.165432 | 0.162345 | 0.168765 |
| Triad | 43789.5 | 44512.3 | 42987.6 | 0.164567 | 0.161234 | 0.167890 |
-------------------------------------------------------------
Solution Validates: avg error less than 1.000000e-13 on all three arrays
-------------------------------------------------------------
Binary file not shown.
Loading
Loading