From 7998b0d01d64f996ae4e62f5392bf4e498d2ecbe Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Tue, 10 Dec 2024 00:28:44 +0100 Subject: [PATCH 01/31] use std::optional for functionid --- include/firestarter/Config/Config.hpp | 4 +- .../firestarter/Environment/Environment.hpp | 8 +- .../Environment/X86/X86Environment.hpp | 8 +- src/firestarter/Config/Config.cpp | 6 +- .../Environment/X86/X86Environment.cpp | 119 +++++++++--------- 5 files changed, 77 insertions(+), 68 deletions(-) diff --git a/include/firestarter/Config/Config.hpp b/include/firestarter/Config/Config.hpp index d0c1448c..17c64e8b 100644 --- a/include/firestarter/Config/Config.hpp +++ b/include/firestarter/Config/Config.hpp @@ -81,8 +81,8 @@ struct Config { int Argc; /// The requested number of threads firestarter should run with. 0 means all threads. std::optional RequestedNumThreads; - /// The selected function id. 0 means automatic selection. - unsigned FunctionId; + /// The selected function id. + std::optional FunctionId; /// The line count of the payload. 0 means default. unsigned LineCount = 0; /// The number of gpus firestarter should stress. Default is -1 means all gpus. diff --git a/include/firestarter/Environment/Environment.hpp b/include/firestarter/Environment/Environment.hpp index 03631166..c2764333 100644 --- a/include/firestarter/Environment/Environment.hpp +++ b/include/firestarter/Environment/Environment.hpp @@ -42,11 +42,13 @@ class Environment { virtual ~Environment() = default; /// Select a PlatformConfig based on its generated id. This function will throw if a payload is not available or the - /// id is incorrect. If id is zero we automatically select a matching PlatformConfig. - /// \arg FunctionId The id of the PlatformConfig that should be selected. + /// id is incorrect. + /// \arg FunctionId The id of the PlatformConfig that should be selected or automatically select a matching + /// PlatformConfig. /// \arg Topology The topology which contains information about the cpu requied to select the correct function. /// \arg AllowUnavailablePayload If true we will not throw if the PlatformConfig is not available. - virtual void selectFunction(unsigned FunctionId, const CPUTopology& Topology, bool AllowUnavailablePayload) = 0; + virtual void selectFunction(std::optional FunctionId, const CPUTopology& Topology, + bool AllowUnavailablePayload) = 0; /// Parse the selected payload instruction groups and save the in the selected function. Throws if the input is /// invalid. diff --git a/include/firestarter/Environment/X86/X86Environment.hpp b/include/firestarter/Environment/X86/X86Environment.hpp index c0e65ab1..c0f138fb 100644 --- a/include/firestarter/Environment/X86/X86Environment.hpp +++ b/include/firestarter/Environment/X86/X86Environment.hpp @@ -67,11 +67,13 @@ class X86Environment final : public Environment { } /// Select a PlatformConfig based on its generated id. This function will throw if a payload is not available or the - /// id is incorrect. If id is zero we automatically select a matching PlatformConfig. - /// \arg FunctionId The id of the PlatformConfig that should be selected. + /// id is incorrect. + /// \arg FunctionId The id of the PlatformConfig that should be selected or automatically select a matching + /// PlatformConfig. /// \arg Topology The topology which contains information about the cpu requied to select the correct function. /// \arg AllowUnavailablePayload If true we will not throw if the PlatformConfig is not available. - void selectFunction(unsigned FunctionId, const CPUTopology& Topology, bool AllowUnavailablePayload) override; + void selectFunction(std::optional FunctionId, const CPUTopology& Topology, + bool AllowUnavailablePayload) override; /// Parse the selected payload instruction groups and save the in the selected function. Throws if the input is /// invalid. diff --git a/src/firestarter/Config/Config.cpp b/src/firestarter/Config/Config.cpp index 6a6dbc3b..e7d99b33 100644 --- a/src/firestarter/Config/Config.cpp +++ b/src/firestarter/Config/Config.cpp @@ -143,7 +143,7 @@ Config::Config(int Argc, const char** Argv) Parser.add_options("general") ("i,function", "Specify integer ID of the load-function to be\nused (as listed by --avail)", - cxxopts::value()->default_value("0"), "ID"); + cxxopts::value(), "ID"); if (firestarter::OptionalFeatures.gpuEnabled()) { Parser.add_options("general") @@ -326,7 +326,9 @@ Config::Config(int Argc, const char** Argv) PrintFunctionSummary = static_cast(Options.count("avail")); - FunctionId = Options["function"].as(); + if (static_cast(Options.count("function"))) { + FunctionId = Options["function"].as(); + } ListInstructionGroups = static_cast(Options.count("list-instruction-groups")); InstructionGroups = Options["run-instruction-groups"].as(); diff --git a/src/firestarter/Environment/X86/X86Environment.cpp b/src/firestarter/Environment/X86/X86Environment.cpp index eae5c7ee..9a10b02f 100644 --- a/src/firestarter/Environment/X86/X86Environment.cpp +++ b/src/firestarter/Environment/X86/X86Environment.cpp @@ -29,86 +29,89 @@ namespace firestarter::environment::x86 { -void X86Environment::selectFunction(unsigned FunctionId, const CPUTopology& Topology, bool AllowUnavailablePayload) { +void X86Environment::selectFunction(std::optional FunctionId, const CPUTopology& Topology, + bool AllowUnavailablePayload) { unsigned Id = 1; std::optional DefaultPayloadName; const auto ProcessorICacheSize = Topology.instructionCacheSize(); const auto ProcessorThreadsPerCore = Topology.homogenousResourceCount().NumThreadsPerCore; - // if functionId is 0 get the default or fallback for (const auto& PlatformConfigPtr : PlatformConfigs) { for (auto const& ThreadsPerCore : PlatformConfigPtr->settings().threads()) { - // the selected function - if (Id == FunctionId) { - if (!PlatformConfigPtr->isAvailable(processorInfos())) { - const auto ErrorString = "Function " + std::to_string(FunctionId) + " (\"" + - PlatformConfigPtr->functionName(ThreadsPerCore) + "\") requires " + - PlatformConfigPtr->payload()->name() + ", which is not supported by the processor."; - if (AllowUnavailablePayload) { - log::warn() << ErrorString; - } else { - throw std::invalid_argument(ErrorString); + if (FunctionId) { + // the selected function + if (Id == *FunctionId) { + if (!PlatformConfigPtr->isAvailable(processorInfos())) { + const auto ErrorString = + "Function " + std::to_string(*FunctionId) + " (\"" + PlatformConfigPtr->functionName(ThreadsPerCore) + + "\") requires " + PlatformConfigPtr->payload()->name() + ", which is not supported by the processor."; + if (AllowUnavailablePayload) { + log::warn() << ErrorString; + } else { + throw std::invalid_argument(ErrorString); + } } - } - // found function - setConfig(PlatformConfigPtr->cloneConcreate(ProcessorICacheSize, ThreadsPerCore)); - return; - } - // default function - if (0 == FunctionId && PlatformConfigPtr->isDefault(processorInfos())) { - if (ThreadsPerCore == ProcessorThreadsPerCore) { + // found function setConfig(PlatformConfigPtr->cloneConcreate(ProcessorICacheSize, ThreadsPerCore)); return; } - DefaultPayloadName = PlatformConfigPtr->payload()->name(); + } else { + // default function + if (PlatformConfigPtr->isDefault(processorInfos())) { + if (ThreadsPerCore == ProcessorThreadsPerCore) { + setConfig(PlatformConfigPtr->cloneConcreate(ProcessorICacheSize, ThreadsPerCore)); + return; + } + DefaultPayloadName = PlatformConfigPtr->payload()->name(); + } + Id++; } - Id++; } } + if (FunctionId) { + throw std::invalid_argument("unknown function id: " + std::to_string(*FunctionId) + + ", see --avail for available ids"); + } + // no default found // use fallback - if (0 == FunctionId) { - if (DefaultPayloadName) { - // default payload available, but number of threads per core is not - // supported - log::warn() << "No " << *DefaultPayloadName << " code path for " << ProcessorThreadsPerCore - << " threads per core!"; - } - log::warn() << processorInfos().vendor() << " " << processorInfos().model() - << " is not supported by this version of FIRESTARTER!\n" - << "Check project website for updates."; - - // loop over available implementation and check if they are marked as - // fallback - for (const auto& FallbackPlatformConfigPtr : FallbackPlatformConfigs) { - if (FallbackPlatformConfigPtr->isAvailable(processorInfos())) { - std::optional SelectedThreadsPerCore; - // find the fallback implementation with the correct thread per core count - for (auto const& ThreadsPerCore : FallbackPlatformConfigPtr->settings().threads()) { - if (ThreadsPerCore == ProcessorThreadsPerCore) { - SelectedThreadsPerCore = ThreadsPerCore; - } - } - // Otherwise select the first available thread per core count - if (!SelectedThreadsPerCore) { - SelectedThreadsPerCore = FallbackPlatformConfigPtr->settings().threads().front(); + if (DefaultPayloadName) { + // default payload available, but number of threads per core is not + // supported + log::warn() << "No " << *DefaultPayloadName << " code path for " << ProcessorThreadsPerCore << " threads per core!"; + } + log::warn() << processorInfos().vendor() << " " << processorInfos().model() + << " is not supported by this version of FIRESTARTER!\n" + << "Check project website for updates."; + + // loop over available implementation and check if they are marked as + // fallback + for (const auto& FallbackPlatformConfigPtr : FallbackPlatformConfigs) { + if (FallbackPlatformConfigPtr->isAvailable(processorInfos())) { + std::optional SelectedThreadsPerCore; + // find the fallback implementation with the correct thread per core count + for (auto const& ThreadsPerCore : FallbackPlatformConfigPtr->settings().threads()) { + if (ThreadsPerCore == ProcessorThreadsPerCore) { + SelectedThreadsPerCore = ThreadsPerCore; } - setConfig(FallbackPlatformConfigPtr->cloneConcreate(ProcessorICacheSize, *SelectedThreadsPerCore)); - log::warn() << "Using function " << FallbackPlatformConfigPtr->functionName(*SelectedThreadsPerCore) - << " as fallback.\n" - << "You can use the parameter --function to try other " - "functions."; - return; } + // Otherwise select the first available thread per core count + if (!SelectedThreadsPerCore) { + SelectedThreadsPerCore = FallbackPlatformConfigPtr->settings().threads().front(); + } + setConfig(FallbackPlatformConfigPtr->cloneConcreate(ProcessorICacheSize, *SelectedThreadsPerCore)); + log::warn() << "Using function " << FallbackPlatformConfigPtr->functionName(*SelectedThreadsPerCore) + << " as fallback.\n" + << "You can use the parameter --function to try other " + "functions."; + return; } - - // no fallback found - throw std::invalid_argument("No fallback implementation found for available ISA " - "extensions."); } - throw std::invalid_argument("unknown function id: " + std::to_string(FunctionId) + ", see --avail for available ids"); + // no fallback found + throw std::invalid_argument("No fallback implementation found for available ISA " + "extensions."); } void X86Environment::selectInstructionGroups(std::string Groups) { From 55e311ed6a231f23b657c4e4f280359d2eb527d0 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Tue, 10 Dec 2024 12:50:35 +0100 Subject: [PATCH 02/31] use PlatformConfig instead of X86PlatformConfig for shared ptrs --- include/firestarter/Environment/X86/X86Environment.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/firestarter/Environment/X86/X86Environment.hpp b/include/firestarter/Environment/X86/X86Environment.hpp index c0f138fb..ccb7eb4b 100644 --- a/include/firestarter/Environment/X86/X86Environment.hpp +++ b/include/firestarter/Environment/X86/X86Environment.hpp @@ -100,7 +100,7 @@ class X86Environment final : public Environment { /// The list of availabe platform configs that is printed when supplying the --avail command line argument. The IDs /// for these configs are generated by iterating through this list starting with 1. To maintain stable IDs in /// FIRESTARTER new configs should be added to the bottom of the list. - const std::list> PlatformConfigs = { + const std::list> PlatformConfigs = { std::make_shared(), std::make_shared(), std::make_shared(), std::make_shared(), std::make_shared(), std::make_shared(), @@ -114,7 +114,7 @@ class X86Environment final : public Environment { /// therefore it is the last on the list. CPUs that support AVX512 will most certainly also support FMA and AVX, /// AVX512 takes precedence. This list should contain one entry for each of the supported CPU extensions by the /// FIRESTARTER payloads. - const std::list> FallbackPlatformConfigs = { + const std::list> FallbackPlatformConfigs = { std::make_shared(), // AVX512 std::make_shared(), // FMA4 std::make_shared(), // FMA From aa98189e9b243348845620780c339f43804a34e0 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Tue, 10 Dec 2024 13:23:18 +0100 Subject: [PATCH 03/31] split X86Environment class into generic and X86 code --- .../firestarter/Environment/Environment.hpp | 19 +++++---- .../Environment/ProcessorInformation.hpp | 10 +++-- .../Environment/X86/X86Environment.hpp | 40 +++++-------------- src/CMakeLists.txt | 5 ++- .../X86Environment.cpp => Environment.cpp} | 28 ++++++------- 5 files changed, 45 insertions(+), 57 deletions(-) rename src/firestarter/Environment/{X86/X86Environment.cpp => Environment.cpp} (88%) diff --git a/include/firestarter/Environment/Environment.hpp b/include/firestarter/Environment/Environment.hpp index c2764333..6090e3b5 100644 --- a/include/firestarter/Environment/Environment.hpp +++ b/include/firestarter/Environment/Environment.hpp @@ -47,28 +47,27 @@ class Environment { /// PlatformConfig. /// \arg Topology The topology which contains information about the cpu requied to select the correct function. /// \arg AllowUnavailablePayload If true we will not throw if the PlatformConfig is not available. - virtual void selectFunction(std::optional FunctionId, const CPUTopology& Topology, - bool AllowUnavailablePayload) = 0; + void selectFunction(std::optional FunctionId, const CPUTopology& Topology, bool AllowUnavailablePayload); /// Parse the selected payload instruction groups and save the in the selected function. Throws if the input is /// invalid. /// \arg Groups The list of instruction groups that is in the format: multiple INSTRUCTION:VALUE pairs /// comma-seperated. - virtual void selectInstructionGroups(std::string Groups) = 0; + void selectInstructionGroups(const std::string& Groups); /// Print the available instruction groups of the selected function. - virtual void printAvailableInstructionGroups() = 0; + void printAvailableInstructionGroups(); /// Set the line count in the selected function. /// \arg LineCount The maximum number of instruction that should be in the high-load loop. - virtual void setLineCount(unsigned LineCount) = 0; + void setLineCount(unsigned LineCount); /// Print a summary of the settings of the selected config. - virtual void printSelectedCodePathSummary() = 0; + void printSelectedCodePathSummary(); /// Print a list of available high-load function and if they are available on the current system. /// \arg ForceYes Force all functions to be shown as avaialable - virtual void printFunctionSummary(bool ForceYes) = 0; + void printFunctionSummary(bool ForceYes) const; /// Getter (which allows modifying) for the current platform config containing the payload, settings and the /// associated name. @@ -89,6 +88,12 @@ class Environment { return *ProcessorInfos; } + [[nodiscard]] virtual auto platformConfigs() const + -> const std::vector>& = 0; + + [[nodiscard]] virtual auto fallbackPlatformConfigs() const + -> const std::vector>& = 0; + protected: /// This function sets the config based on the void setConfig(std::unique_ptr&& Config) { this->Config = std::move(Config); } diff --git a/include/firestarter/Environment/ProcessorInformation.hpp b/include/firestarter/Environment/ProcessorInformation.hpp index 25520260..8e859534 100644 --- a/include/firestarter/Environment/ProcessorInformation.hpp +++ b/include/firestarter/Environment/ProcessorInformation.hpp @@ -47,15 +47,17 @@ class ProcessorInformation { /// Get the current hardware timestamp [[nodiscard]] virtual auto timestamp() const -> uint64_t = 0; + /// The CPU vendor i.e., Intel or AMD. + [[nodiscard]] virtual auto vendor() const -> std::string const& { return Vendor; } + + /// The model of the processor. With X86 this is the the string of Family, Model and Stepping. + [[nodiscard]] virtual auto model() const -> std::string const& = 0; + protected: /// The CPU architecture e.g., x86_64 [[nodiscard]] auto architecture() const -> std::string const& { return Architecture; } - /// The CPU vendor i.e., Intel or AMD. - [[nodiscard]] virtual auto vendor() const -> std::string const& { return Vendor; } /// The processor name, this includes the vendor specific name [[nodiscard]] virtual auto processorName() const -> std::string const& { return ProcessorName; } - /// The model of the processor. With X86 this is the the string of Family, Model and Stepping. - [[nodiscard]] virtual auto model() const -> std::string const& = 0; /// Getter for the list of CPU features [[nodiscard]] virtual auto features() const -> std::list const& = 0; diff --git a/include/firestarter/Environment/X86/X86Environment.hpp b/include/firestarter/Environment/X86/X86Environment.hpp index ccb7eb4b..7fb689bd 100644 --- a/include/firestarter/Environment/X86/X86Environment.hpp +++ b/include/firestarter/Environment/X86/X86Environment.hpp @@ -66,41 +66,21 @@ class X86Environment final : public Environment { return *X86Topology; } - /// Select a PlatformConfig based on its generated id. This function will throw if a payload is not available or the - /// id is incorrect. - /// \arg FunctionId The id of the PlatformConfig that should be selected or automatically select a matching - /// PlatformConfig. - /// \arg Topology The topology which contains information about the cpu requied to select the correct function. - /// \arg AllowUnavailablePayload If true we will not throw if the PlatformConfig is not available. - void selectFunction(std::optional FunctionId, const CPUTopology& Topology, - bool AllowUnavailablePayload) override; - - /// Parse the selected payload instruction groups and save the in the selected function. Throws if the input is - /// invalid. - /// \arg Groups The list of instruction groups that is in the format: multiple INSTRUCTION:VALUE pairs - /// comma-seperated. - void selectInstructionGroups(std::string Groups) override; - - /// Print the available instruction groups of the selected function. - void printAvailableInstructionGroups() override; - - /// Set the line count in the selected function. - /// \arg LineCount The maximum number of instruction that should be in the high-load loop. - void setLineCount(unsigned LineCount) override; - - /// Print a summary of the settings of the selected config. - void printSelectedCodePathSummary() override; + [[nodiscard]] auto platformConfigs() const + -> const std::vector>& override { + return PlatformConfigs; + } - /// Print a list of available high-load function and if they are available on the current system. This includes all - /// PlatformConfigs in combination with all thread per core counts. - /// \arg ForceYes Force all functions to be shown as avaialable - void printFunctionSummary(bool ForceYes) override; + [[nodiscard]] auto fallbackPlatformConfigs() const + -> const std::vector>& override { + return FallbackPlatformConfigs; + } private: /// The list of availabe platform configs that is printed when supplying the --avail command line argument. The IDs /// for these configs are generated by iterating through this list starting with 1. To maintain stable IDs in /// FIRESTARTER new configs should be added to the bottom of the list. - const std::list> PlatformConfigs = { + const std::vector> PlatformConfigs = { std::make_shared(), std::make_shared(), std::make_shared(), std::make_shared(), std::make_shared(), std::make_shared(), @@ -114,7 +94,7 @@ class X86Environment final : public Environment { /// therefore it is the last on the list. CPUs that support AVX512 will most certainly also support FMA and AVX, /// AVX512 takes precedence. This list should contain one entry for each of the supported CPU extensions by the /// FIRESTARTER payloads. - const std::list> FallbackPlatformConfigs = { + const std::vector> FallbackPlatformConfigs = { std::make_shared(), // AVX512 std::make_shared(), // FMA4 std::make_shared(), // FMA diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6361218c..aa0930cd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,15 +10,16 @@ add_library(firestartercore STATIC firestarter/Config/Config.cpp firestarter/Config/CpuBind.cpp - firestarter/Environment/X86/Platform/X86PlatformConfig.cpp + firestarter/Environment/Environment.cpp firestarter/Environment/ProcessorInformation.cpp firestarter/Environment/Payload/CompiledPayload.cpp firestarter/Environment/Payload/PayloadSettings.cpp # here starts the x86 specific code - firestarter/Environment/X86/X86Environment.cpp firestarter/Environment/X86/X86ProcessorInformation.cpp + + firestarter/Environment/X86/Platform/X86PlatformConfig.cpp firestarter/Environment/X86/Payload/X86Payload.cpp firestarter/Environment/X86/Payload/AVX512Payload.cpp diff --git a/src/firestarter/Environment/X86/X86Environment.cpp b/src/firestarter/Environment/Environment.cpp similarity index 88% rename from src/firestarter/Environment/X86/X86Environment.cpp rename to src/firestarter/Environment/Environment.cpp index 9a10b02f..5a178250 100644 --- a/src/firestarter/Environment/X86/X86Environment.cpp +++ b/src/firestarter/Environment/Environment.cpp @@ -1,6 +1,6 @@ /****************************************************************************** * FIRESTARTER - A Processor Stress Test Utility - * Copyright (C) 2020-2023 TU Dresden, Center for Information Services and High + * Copyright (C) 2020-2024 TU Dresden, Center for Information Services and High * Performance Computing * * This program is free software: you can redistribute it and/or modify @@ -19,7 +19,7 @@ * Contact: daniel.hackenberg@tu-dresden.de *****************************************************************************/ -#include "firestarter/Environment/X86/X86Environment.hpp" +#include "firestarter/Environment/Environment.hpp" #include "firestarter/Logging/Log.hpp" #include @@ -27,16 +27,16 @@ #include #include -namespace firestarter::environment::x86 { +namespace firestarter::environment { -void X86Environment::selectFunction(std::optional FunctionId, const CPUTopology& Topology, - bool AllowUnavailablePayload) { +void Environment::selectFunction(std::optional FunctionId, const CPUTopology& Topology, + bool AllowUnavailablePayload) { unsigned Id = 1; std::optional DefaultPayloadName; const auto ProcessorICacheSize = Topology.instructionCacheSize(); const auto ProcessorThreadsPerCore = Topology.homogenousResourceCount().NumThreadsPerCore; - for (const auto& PlatformConfigPtr : PlatformConfigs) { + for (const auto& PlatformConfigPtr : platformConfigs()) { for (auto const& ThreadsPerCore : PlatformConfigPtr->settings().threads()) { if (FunctionId) { // the selected function @@ -87,7 +87,7 @@ void X86Environment::selectFunction(std::optional FunctionId, const CP // loop over available implementation and check if they are marked as // fallback - for (const auto& FallbackPlatformConfigPtr : FallbackPlatformConfigs) { + for (const auto& FallbackPlatformConfigPtr : fallbackPlatformConfigs()) { if (FallbackPlatformConfigPtr->isAvailable(processorInfos())) { std::optional SelectedThreadsPerCore; // find the fallback implementation with the correct thread per core count @@ -114,7 +114,7 @@ void X86Environment::selectFunction(std::optional FunctionId, const CP "extensions."); } -void X86Environment::selectInstructionGroups(std::string Groups) { +void Environment::selectInstructionGroups(const std::string& Groups) { const auto Delimiter = ','; const std::regex Re("^(\\w+):(\\d+)$"); const auto AvailableInstructionGroups = config().payload()->getAvailableInstructions(); @@ -153,7 +153,7 @@ void X86Environment::selectInstructionGroups(std::string Groups) { log::info() << " Running custom instruction group: " << Groups; } -void X86Environment::printAvailableInstructionGroups() { +void Environment::printAvailableInstructionGroups() { std::stringstream Ss; for (auto const& Item : config().payload()->getAvailableInstructions()) { @@ -169,11 +169,11 @@ void X86Environment::printAvailableInstructionGroups() { << " " << S; } -void X86Environment::setLineCount(unsigned LineCount) { config().settings().setLineCount(LineCount); } +void Environment::setLineCount(unsigned LineCount) { config().settings().setLineCount(LineCount); } -void X86Environment::printSelectedCodePathSummary() { config().printCodePathSummary(); } +void Environment::printSelectedCodePathSummary() { config().printCodePathSummary(); } -void X86Environment::printFunctionSummary(bool ForceYes) { +void Environment::printFunctionSummary(bool ForceYes) const { log::info() << " available load-functions:\n" << " ID | NAME | available on this " "system | payload default setting\n" @@ -184,7 +184,7 @@ void X86Environment::printFunctionSummary(bool ForceYes) { auto Id = 1U; - for (auto const& Config : PlatformConfigs) { + for (auto const& Config : platformConfigs()) { for (auto const& ThreadsPerCore : Config->settings().threads()) { const char* Available = (Config->isAvailable(processorInfos()) || ForceYes) ? "yes" : "no"; const auto& FunctionName = Config->functionName(ThreadsPerCore); @@ -197,4 +197,4 @@ void X86Environment::printFunctionSummary(bool ForceYes) { } } -} // namespace firestarter::environment::x86 \ No newline at end of file +} // namespace firestarter::environment \ No newline at end of file From 57259a1c5dce3b90a71520abc068af8aab37bb56 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Tue, 10 Dec 2024 14:25:33 +0100 Subject: [PATCH 04/31] move files from Environment folder one up --- .../{Environment => }/Environment.hpp | 12 ++--- include/firestarter/Firestarter.hpp | 2 +- include/firestarter/LoadWorkerData.hpp | 24 +++++----- .../Payload/CompiledPayload.hpp | 6 +-- .../{Environment => }/Payload/Payload.hpp | 10 ++--- .../Payload/PayloadSettings.hpp | 4 +- .../Payload/PayloadStats.hpp | 4 +- .../Platform/PlatformConfig.hpp | 8 ++-- .../ProcessorInformation.hpp | 4 +- .../X86/Payload/AVX512Payload.hpp | 10 ++--- .../X86/Payload/AVXPayload.hpp | 10 ++--- .../X86/Payload/CompiledX86Payload.hpp | 14 +++--- .../X86/Payload/FMA4Payload.hpp | 10 ++--- .../X86/Payload/FMAPayload.hpp | 10 ++--- .../X86/Payload/SSE2Payload.hpp | 10 ++--- .../X86/Payload/X86Payload.hpp | 10 ++--- .../X86/Payload/ZENFMAPayload.hpp | 10 ++--- .../X86/Platform/BulldozerConfig.hpp | 10 ++--- .../X86/Platform/HaswellConfig.hpp | 10 ++--- .../X86/Platform/HaswellEPConfig.hpp | 10 ++--- .../X86/Platform/KnightsLandingConfig.hpp | 10 ++--- .../X86/Platform/NaplesConfig.hpp | 10 ++--- .../X86/Platform/NehalemConfig.hpp | 10 ++--- .../X86/Platform/NehalemEPConfig.hpp | 10 ++--- .../X86/Platform/RomeConfig.hpp | 10 ++--- .../X86/Platform/SandyBridgeConfig.hpp | 10 ++--- .../X86/Platform/SandyBridgeEPConfig.hpp | 10 ++--- .../X86/Platform/SkylakeConfig.hpp | 10 ++--- .../X86/Platform/SkylakeSPConfig.hpp | 10 ++--- .../X86/Platform/X86PlatformConfig.hpp | 20 ++++----- .../{Environment => }/X86/X86Environment.hpp | 40 ++++++++--------- .../X86/X86ProcessorInformation.hpp | 6 +-- src/CMakeLists.txt | 31 +++++++------ .../{Environment => }/Environment.cpp | 6 +-- src/firestarter/Firestarter.cpp | 24 +++++----- src/firestarter/LoadWorker.cpp | 4 +- .../Payload/CompiledPayload.cpp | 8 ++-- .../Payload/PayloadSettings.cpp | 6 +-- .../ProcessorInformation.cpp | 6 +-- .../X86/Payload/AVX512Payload.cpp | 28 ++++++------ .../X86/Payload/AVXPayload.cpp | 28 ++++++------ .../X86/Payload/FMA4Payload.cpp | 28 ++++++------ .../X86/Payload/FMAPayload.cpp | 28 ++++++------ .../X86/Payload/SSE2Payload.cpp | 28 ++++++------ .../X86/Payload/X86Payload.cpp | 6 +-- .../X86/Payload/ZENFMAPayload.cpp | 28 ++++++------ .../X86/Platform/X86PlatformConfig.cpp | 2 +- .../X86/X86ProcessorInformation.cpp | 6 +-- test/DumpPayloads/Main.cpp | 44 +++++++++---------- test/X86Functions/Main.cpp | 4 +- 50 files changed, 329 insertions(+), 330 deletions(-) rename include/firestarter/{Environment => }/Environment.hpp (91%) rename include/firestarter/{Environment => }/Payload/CompiledPayload.hpp (96%) rename include/firestarter/{Environment => }/Payload/Payload.hpp (94%) rename include/firestarter/{Environment => }/Payload/PayloadSettings.hpp (99%) rename include/firestarter/{Environment => }/Payload/PayloadStats.hpp (93%) rename include/firestarter/{Environment => }/Platform/PlatformConfig.hpp (96%) rename include/firestarter/{Environment => }/ProcessorInformation.hpp (97%) rename include/firestarter/{Environment => }/X86/Payload/AVX512Payload.hpp (91%) rename include/firestarter/{Environment => }/X86/Payload/AVXPayload.hpp (91%) rename include/firestarter/{Environment => }/X86/Payload/CompiledX86Payload.hpp (89%) rename include/firestarter/{Environment => }/X86/Payload/FMA4Payload.hpp (91%) rename include/firestarter/{Environment => }/X86/Payload/FMAPayload.hpp (91%) rename include/firestarter/{Environment => }/X86/Payload/SSE2Payload.hpp (91%) rename include/firestarter/{Environment => }/X86/Payload/X86Payload.hpp (98%) rename include/firestarter/{Environment => }/X86/Payload/ZENFMAPayload.hpp (89%) rename include/firestarter/{Environment => }/X86/Platform/BulldozerConfig.hpp (84%) rename include/firestarter/{Environment => }/X86/Platform/HaswellConfig.hpp (84%) rename include/firestarter/{Environment => }/X86/Platform/HaswellEPConfig.hpp (84%) rename include/firestarter/{Environment => }/X86/Platform/KnightsLandingConfig.hpp (84%) rename include/firestarter/{Environment => }/X86/Platform/NaplesConfig.hpp (84%) rename include/firestarter/{Environment => }/X86/Platform/NehalemConfig.hpp (83%) rename include/firestarter/{Environment => }/X86/Platform/NehalemEPConfig.hpp (84%) rename include/firestarter/{Environment => }/X86/Platform/RomeConfig.hpp (84%) rename include/firestarter/{Environment => }/X86/Platform/SandyBridgeConfig.hpp (84%) rename include/firestarter/{Environment => }/X86/Platform/SandyBridgeEPConfig.hpp (84%) rename include/firestarter/{Environment => }/X86/Platform/SkylakeConfig.hpp (84%) rename include/firestarter/{Environment => }/X86/Platform/SkylakeSPConfig.hpp (88%) rename include/firestarter/{Environment => }/X86/Platform/X86PlatformConfig.hpp (88%) rename include/firestarter/{Environment => }/X86/X86Environment.hpp (75%) rename include/firestarter/{Environment => }/X86/X86ProcessorInformation.hpp (96%) rename src/firestarter/{Environment => }/Environment.cpp (98%) rename src/firestarter/{Environment => }/Payload/CompiledPayload.cpp (85%) rename src/firestarter/{Environment => }/Payload/PayloadSettings.cpp (95%) rename src/firestarter/{Environment => }/ProcessorInformation.cpp (97%) rename src/firestarter/{Environment => }/X86/Payload/AVX512Payload.cpp (94%) rename src/firestarter/{Environment => }/X86/Payload/AVXPayload.cpp (94%) rename src/firestarter/{Environment => }/X86/Payload/FMA4Payload.cpp (94%) rename src/firestarter/{Environment => }/X86/Payload/FMAPayload.cpp (94%) rename src/firestarter/{Environment => }/X86/Payload/SSE2Payload.cpp (94%) rename src/firestarter/{Environment => }/X86/Payload/X86Payload.cpp (95%) rename src/firestarter/{Environment => }/X86/Payload/ZENFMAPayload.cpp (93%) rename src/firestarter/{Environment => }/X86/Platform/X86PlatformConfig.cpp (95%) rename src/firestarter/{Environment => }/X86/X86ProcessorInformation.cpp (97%) diff --git a/include/firestarter/Environment/Environment.hpp b/include/firestarter/Environment.hpp similarity index 91% rename from include/firestarter/Environment/Environment.hpp rename to include/firestarter/Environment.hpp index 6090e3b5..18bec434 100644 --- a/include/firestarter/Environment/Environment.hpp +++ b/include/firestarter/Environment.hpp @@ -22,13 +22,13 @@ #pragma once #include "firestarter/CPUTopology.hpp" -#include "firestarter/Environment/Platform/PlatformConfig.hpp" -#include "firestarter/Environment/ProcessorInformation.hpp" +#include "firestarter/Platform/PlatformConfig.hpp" +#include "firestarter/ProcessorInformation.hpp" #include #include -namespace firestarter::environment { +namespace firestarter { /// This class handles parsing of user input to FIRESTARTER, namely the number of threads used, the thread affinity, the /// selection of the correct high-load function, selection of the instruction groups and number of lines. It also @@ -89,10 +89,10 @@ class Environment { } [[nodiscard]] virtual auto platformConfigs() const - -> const std::vector>& = 0; + -> const std::vector>& = 0; [[nodiscard]] virtual auto fallbackPlatformConfigs() const - -> const std::vector>& = 0; + -> const std::vector>& = 0; protected: /// This function sets the config based on the @@ -105,4 +105,4 @@ class Environment { std::unique_ptr ProcessorInfos; }; -} // namespace firestarter::environment +} // namespace firestarter diff --git a/include/firestarter/Firestarter.hpp b/include/firestarter/Firestarter.hpp index 4a8e5e7d..a90fa3cb 100644 --- a/include/firestarter/Firestarter.hpp +++ b/include/firestarter/Firestarter.hpp @@ -69,7 +69,7 @@ class Firestarter { /// This class handles getting the topology information of the processor and is used to set thread binding. std::unique_ptr Topology; /// The class that handles setting up the payload for firestarter - std::unique_ptr Environment; + std::unique_ptr EnvironmentPtr; /// The class for execution of the gemm routine on Cuda or HIP GPUs. std::unique_ptr Cuda; /// The class for execution of the gemm routine on OneAPI GPUs. diff --git a/include/firestarter/LoadWorkerData.hpp b/include/firestarter/LoadWorkerData.hpp index b64f0697..649dded7 100644 --- a/include/firestarter/LoadWorkerData.hpp +++ b/include/firestarter/LoadWorkerData.hpp @@ -23,9 +23,9 @@ #include "firestarter/CPUTopology.hpp" #include "firestarter/Constants.hpp" -#include "firestarter/Environment/Environment.hpp" -#include "firestarter/Environment/Platform/PlatformConfig.hpp" +#include "firestarter/Environment.hpp" #include "firestarter/LoadWorkerMemory.hpp" +#include "firestarter/Platform/PlatformConfig.hpp" #include #include @@ -72,18 +72,18 @@ class LoadWorkerData { /// compiled payload. /// \arg ErrorDetection Should the code to support error detection between thread be baked into the high load routine /// of the compiled payload. - LoadWorkerData(uint64_t Id, uint64_t OsIndex, const environment::Environment& Environment, - const CPUTopology& Topology, volatile LoadThreadWorkType& LoadVar, std::chrono::microseconds Period, - bool DumpRegisters, bool ErrorDetection) + LoadWorkerData(uint64_t Id, uint64_t OsIndex, const Environment& EnvironmentRef, const CPUTopology& Topology, + volatile LoadThreadWorkType& LoadVar, std::chrono::microseconds Period, bool DumpRegisters, + bool ErrorDetection) : LoadVar(LoadVar) , Period(Period) , DumpRegisters(DumpRegisters) , ErrorDetection(ErrorDetection) , Id(Id) , OsIndex(OsIndex) - , Environment(Environment) + , EnvironmentRef(EnvironmentRef) , Topology(Topology) - , Config(Environment.config().clone()) {} + , Config(EnvironmentRef.config().clone()) {} ~LoadWorkerData() = default; @@ -100,9 +100,9 @@ class LoadWorkerData { /// Gettter for the id of the thread. [[nodiscard]] auto id() const -> uint64_t { return Id; } /// Const getter for the environment. - [[nodiscard]] auto environment() const -> const environment::Environment& { return Environment; } + [[nodiscard]] auto environment() const -> const Environment& { return EnvironmentRef; } /// Getter for the current platform config. - [[nodiscard]] auto config() const -> environment::platform::PlatformConfig& { return *Config; } + [[nodiscard]] auto config() const -> platform::PlatformConfig& { return *Config; } /// Access the DumpRegisterStruct. Asserts when dumping registers is not enabled. /// \returns a reference to the DumpRegisterStruct @@ -132,7 +132,7 @@ class LoadWorkerData { LoadWorkerMemory::UniquePtr Memory = {nullptr, nullptr}; /// The compiled payload which contains the pointers to the specific functions which are executed and some stats. - environment::payload::CompiledPayload::UniquePtr CompiledPayloadPtr = {nullptr, nullptr}; + payload::CompiledPayload::UniquePtr CompiledPayloadPtr = {nullptr, nullptr}; /// The variable that controls the execution of the load worker. volatile LoadThreadWorkType& LoadVar; @@ -166,11 +166,11 @@ class LoadWorkerData { /// The os index to which this thread should be bound. const uint64_t OsIndex; /// The reference to the environment which allows getting the current timestamp. - const environment::Environment& Environment; + const Environment& EnvironmentRef; /// The reference to the processor topology abstraction which allows setting thread affinity. const CPUTopology& Topology; /// The config that is cloned from the environment for this specfic load worker. - std::unique_ptr Config; + std::unique_ptr Config; }; } // namespace firestarter diff --git a/include/firestarter/Environment/Payload/CompiledPayload.hpp b/include/firestarter/Payload/CompiledPayload.hpp similarity index 96% rename from include/firestarter/Environment/Payload/CompiledPayload.hpp rename to include/firestarter/Payload/CompiledPayload.hpp index 488c6c8d..ba78a580 100644 --- a/include/firestarter/Environment/Payload/CompiledPayload.hpp +++ b/include/firestarter/Payload/CompiledPayload.hpp @@ -22,13 +22,13 @@ #pragma once #include "firestarter/Constants.hpp" -#include "firestarter/Environment/Payload/PayloadStats.hpp" +#include "firestarter/Payload/PayloadStats.hpp" #include #include #include -namespace firestarter::environment::payload { +namespace firestarter::payload { class Payload; @@ -98,4 +98,4 @@ class CompiledPayload { HighLoadFunctionPtr HighLoadFunction; }; -} // namespace firestarter::environment::payload \ No newline at end of file +} // namespace firestarter::payload \ No newline at end of file diff --git a/include/firestarter/Environment/Payload/Payload.hpp b/include/firestarter/Payload/Payload.hpp similarity index 94% rename from include/firestarter/Environment/Payload/Payload.hpp rename to include/firestarter/Payload/Payload.hpp index 10bf0e03..8a465808 100644 --- a/include/firestarter/Environment/Payload/Payload.hpp +++ b/include/firestarter/Payload/Payload.hpp @@ -22,16 +22,16 @@ #pragma once #include "firestarter/Constants.hpp" -#include "firestarter/Environment/Payload/CompiledPayload.hpp" -#include "firestarter/Environment/Payload/PayloadSettings.hpp" -#include "firestarter/Environment/ProcessorInformation.hpp" +#include "firestarter/Payload/CompiledPayload.hpp" +#include "firestarter/Payload/PayloadSettings.hpp" +#include "firestarter/ProcessorInformation.hpp" #include #include #include #include -namespace firestarter::environment::payload { +namespace firestarter::payload { class Payload { private: @@ -104,4 +104,4 @@ class Payload { [[nodiscard]] virtual auto getAvailableInstructions() const -> std::list = 0; }; -} // namespace firestarter::environment::payload +} // namespace firestarter::payload diff --git a/include/firestarter/Environment/Payload/PayloadSettings.hpp b/include/firestarter/Payload/PayloadSettings.hpp similarity index 99% rename from include/firestarter/Environment/Payload/PayloadSettings.hpp rename to include/firestarter/Payload/PayloadSettings.hpp index 8438e9a6..68e617a8 100644 --- a/include/firestarter/Environment/Payload/PayloadSettings.hpp +++ b/include/firestarter/Payload/PayloadSettings.hpp @@ -30,7 +30,7 @@ #include #include -namespace firestarter::environment::payload { +namespace firestarter::payload { /// This class represents the settings that can be changed in the high load routine of a payload. struct PayloadSettings { @@ -265,4 +265,4 @@ struct PayloadSettings { void setLineCount(unsigned LineCount) { this->Lines = LineCount; } }; -} // namespace firestarter::environment::payload +} // namespace firestarter::payload diff --git a/include/firestarter/Environment/Payload/PayloadStats.hpp b/include/firestarter/Payload/PayloadStats.hpp similarity index 93% rename from include/firestarter/Environment/Payload/PayloadStats.hpp rename to include/firestarter/Payload/PayloadStats.hpp index 79b2b1e3..d240743f 100644 --- a/include/firestarter/Environment/Payload/PayloadStats.hpp +++ b/include/firestarter/Payload/PayloadStats.hpp @@ -21,7 +21,7 @@ #pragma once -namespace firestarter::environment::payload { +namespace firestarter::payload { /// This struct represents the stats a compiled payload has. struct PayloadStats { @@ -35,4 +35,4 @@ struct PayloadStats { unsigned Instructions = 0; }; -} // namespace firestarter::environment::payload +} // namespace firestarter::payload diff --git a/include/firestarter/Environment/Platform/PlatformConfig.hpp b/include/firestarter/Platform/PlatformConfig.hpp similarity index 96% rename from include/firestarter/Environment/Platform/PlatformConfig.hpp rename to include/firestarter/Platform/PlatformConfig.hpp index e077ce21..e9a49058 100644 --- a/include/firestarter/Environment/Platform/PlatformConfig.hpp +++ b/include/firestarter/Platform/PlatformConfig.hpp @@ -21,11 +21,11 @@ #pragma once -#include "firestarter/Environment/Payload/Payload.hpp" -#include "firestarter/Environment/ProcessorInformation.hpp" +#include "firestarter/Payload/Payload.hpp" +#include "firestarter/ProcessorInformation.hpp" #include "firestarter/Logging/Log.hpp" -namespace firestarter::environment::platform { +namespace firestarter::platform { /// The payload in combination with settings and a short hand name for the specific microarchitecture this payload is /// designed for. @@ -135,4 +135,4 @@ class PlatformConfig { } }; -} // namespace firestarter::environment::platform +} // namespace firestarter::platform diff --git a/include/firestarter/Environment/ProcessorInformation.hpp b/include/firestarter/ProcessorInformation.hpp similarity index 97% rename from include/firestarter/Environment/ProcessorInformation.hpp rename to include/firestarter/ProcessorInformation.hpp index 8e859534..e8d8cefe 100644 --- a/include/firestarter/Environment/ProcessorInformation.hpp +++ b/include/firestarter/ProcessorInformation.hpp @@ -31,7 +31,7 @@ extern "C" { #include } -namespace firestarter::environment { +namespace firestarter { /// This class models the properties of a processor. class ProcessorInformation { @@ -88,4 +88,4 @@ inline auto operator<<(std::ostream& Stream, ProcessorInformation const& CpuTopo return CpuTopologyRef.print(Stream); } -} // namespace firestarter::environment +} // namespace firestarter diff --git a/include/firestarter/Environment/X86/Payload/AVX512Payload.hpp b/include/firestarter/X86/Payload/AVX512Payload.hpp similarity index 91% rename from include/firestarter/Environment/X86/Payload/AVX512Payload.hpp rename to include/firestarter/X86/Payload/AVX512Payload.hpp index d783b984..6bc42b79 100644 --- a/include/firestarter/Environment/X86/Payload/AVX512Payload.hpp +++ b/include/firestarter/X86/Payload/AVX512Payload.hpp @@ -21,9 +21,9 @@ #pragma once -#include "firestarter/Environment/X86/Payload/X86Payload.hpp" +#include "firestarter/X86/Payload/X86Payload.hpp" -namespace firestarter::environment::x86::payload { +namespace firestarter::x86::payload { /// This payload is designed for the AVX512 foundation CPU extension. class AVX512Payload final : public X86Payload { @@ -58,9 +58,9 @@ class AVX512Payload final : public X86Payload { /// of the compiled payload. /// \arg PrintAssembler Should the generated assembler code be logged. /// \returns The compiled payload that provides access to the init and load functions. - [[nodiscard]] auto compilePayload(const environment::payload::PayloadSettings& Settings, bool DumpRegisters, + [[nodiscard]] auto compilePayload(const firestarter::payload::PayloadSettings& Settings, bool DumpRegisters, bool ErrorDetection, bool PrintAssembler) const - -> environment::payload::CompiledPayload::UniquePtr override; + -> firestarter::payload::CompiledPayload::UniquePtr override; private: /// Function to initialize the memory used by the high load function. @@ -68,4 +68,4 @@ class AVX512Payload final : public X86Payload { /// \arg BufferSize The number of doubles that is allocated in MemoryAddr. void init(double* MemoryAddr, uint64_t BufferSize) const override; }; -} // namespace firestarter::environment::x86::payload +} // namespace firestarter::x86::payload diff --git a/include/firestarter/Environment/X86/Payload/AVXPayload.hpp b/include/firestarter/X86/Payload/AVXPayload.hpp similarity index 91% rename from include/firestarter/Environment/X86/Payload/AVXPayload.hpp rename to include/firestarter/X86/Payload/AVXPayload.hpp index db9c1a42..db981ba8 100644 --- a/include/firestarter/Environment/X86/Payload/AVXPayload.hpp +++ b/include/firestarter/X86/Payload/AVXPayload.hpp @@ -21,9 +21,9 @@ #pragma once -#include "firestarter/Environment/X86/Payload/X86Payload.hpp" +#include "firestarter/X86/Payload/X86Payload.hpp" -namespace firestarter::environment::x86::payload { +namespace firestarter::x86::payload { /// This payload is designed for the AVX CPU extension. class AVXPayload final : public X86Payload { @@ -57,9 +57,9 @@ class AVXPayload final : public X86Payload { /// of the compiled payload. /// \arg PrintAssembler Should the generated assembler code be logged. /// \returns The compiled payload that provides access to the init and load functions. - [[nodiscard]] auto compilePayload(const environment::payload::PayloadSettings& Settings, bool DumpRegisters, + [[nodiscard]] auto compilePayload(const firestarter::payload::PayloadSettings& Settings, bool DumpRegisters, bool ErrorDetection, bool PrintAssembler) const - -> environment::payload::CompiledPayload::UniquePtr override; + -> firestarter::payload::CompiledPayload::UniquePtr override; private: /// Function to initialize the memory used by the high load function. @@ -67,4 +67,4 @@ class AVXPayload final : public X86Payload { /// \arg BufferSize The number of doubles that is allocated in MemoryAddr. void init(double* MemoryAddr, uint64_t BufferSize) const override; }; -} // namespace firestarter::environment::x86::payload +} // namespace firestarter::x86::payload diff --git a/include/firestarter/Environment/X86/Payload/CompiledX86Payload.hpp b/include/firestarter/X86/Payload/CompiledX86Payload.hpp similarity index 89% rename from include/firestarter/Environment/X86/Payload/CompiledX86Payload.hpp rename to include/firestarter/X86/Payload/CompiledX86Payload.hpp index 776f83f4..9a08f9c1 100644 --- a/include/firestarter/Environment/X86/Payload/CompiledX86Payload.hpp +++ b/include/firestarter/X86/Payload/CompiledX86Payload.hpp @@ -21,17 +21,17 @@ #pragma once -#include "firestarter/Environment/Payload/CompiledPayload.hpp" #include "firestarter/Logging/Log.hpp" +#include "firestarter/Payload/CompiledPayload.hpp" #include #include -namespace firestarter::environment::x86::payload { +namespace firestarter::x86::payload { /// This class provides the functionality to compile a payload created with asmjit and create a unique pointer to the /// CompiledPayload class which can be used to execute the functions of this payload. -class CompiledX86Payload final : public environment::payload::CompiledPayload { +class CompiledX86Payload final : public firestarter::payload::CompiledPayload { private: // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) inline static asmjit::JitRuntime Runtime = asmjit::JitRuntime(); @@ -52,8 +52,8 @@ class CompiledX86Payload final : public environment::payload::CompiledPayload { /// \arg PayloadPtr A unique pointer to the payload class to allow calling the init and low load functions which do /// not change based on different payload settings. /// \arg HighLoadFunction The pointer to the compiled high load function. - CompiledX86Payload(const environment::payload::PayloadStats& Stats, - std::unique_ptr&& PayloadPtr, HighLoadFunctionPtr HighLoadFunction) + CompiledX86Payload(const firestarter::payload::PayloadStats& Stats, + std::unique_ptr&& PayloadPtr, HighLoadFunctionPtr HighLoadFunction) : CompiledPayload(Stats, std::move(PayloadPtr), HighLoadFunction) {} public: @@ -67,7 +67,7 @@ class CompiledX86Payload final : public environment::payload::CompiledPayload { /// JitRuntime and a pointer to the function will be provided to the CompiledPayload class. /// \returns The unique pointer to the compiled payload. template - [[nodiscard]] static auto create(environment::payload::PayloadStats Stats, asmjit::CodeHolder& Code) -> UniquePtr { + [[nodiscard]] static auto create(firestarter::payload::PayloadStats Stats, asmjit::CodeHolder& Code) -> UniquePtr { HighLoadFunctionPtr HighLoadFunction{}; const auto Err = Runtime.add(&HighLoadFunction, &Code); if (Err) { @@ -78,4 +78,4 @@ class CompiledX86Payload final : public environment::payload::CompiledPayload { } }; -} // namespace firestarter::environment::x86::payload +} // namespace firestarter::x86::payload diff --git a/include/firestarter/Environment/X86/Payload/FMA4Payload.hpp b/include/firestarter/X86/Payload/FMA4Payload.hpp similarity index 91% rename from include/firestarter/Environment/X86/Payload/FMA4Payload.hpp rename to include/firestarter/X86/Payload/FMA4Payload.hpp index 13e66550..9851c28f 100644 --- a/include/firestarter/Environment/X86/Payload/FMA4Payload.hpp +++ b/include/firestarter/X86/Payload/FMA4Payload.hpp @@ -21,9 +21,9 @@ #pragma once -#include "firestarter/Environment/X86/Payload/X86Payload.hpp" +#include "firestarter/X86/Payload/X86Payload.hpp" -namespace firestarter::environment::x86::payload { +namespace firestarter::x86::payload { /// This payload is designed for the FMA4 CPU extension. class FMA4Payload final : public X86Payload { @@ -57,9 +57,9 @@ class FMA4Payload final : public X86Payload { /// of the compiled payload. /// \arg PrintAssembler Should the generated assembler code be logged. /// \returns The compiled payload that provides access to the init and load functions. - [[nodiscard]] auto compilePayload(const environment::payload::PayloadSettings& Settings, bool DumpRegisters, + [[nodiscard]] auto compilePayload(const firestarter::payload::PayloadSettings& Settings, bool DumpRegisters, bool ErrorDetection, bool PrintAssembler) const - -> environment::payload::CompiledPayload::UniquePtr override; + -> firestarter::payload::CompiledPayload::UniquePtr override; private: /// Function to initialize the memory used by the high load function. @@ -67,4 +67,4 @@ class FMA4Payload final : public X86Payload { /// \arg BufferSize The number of doubles that is allocated in MemoryAddr. void init(double* MemoryAddr, uint64_t BufferSize) const override; }; -} // namespace firestarter::environment::x86::payload \ No newline at end of file +} // namespace firestarter::x86::payload \ No newline at end of file diff --git a/include/firestarter/Environment/X86/Payload/FMAPayload.hpp b/include/firestarter/X86/Payload/FMAPayload.hpp similarity index 91% rename from include/firestarter/Environment/X86/Payload/FMAPayload.hpp rename to include/firestarter/X86/Payload/FMAPayload.hpp index 1bfe361b..82c178b8 100644 --- a/include/firestarter/Environment/X86/Payload/FMAPayload.hpp +++ b/include/firestarter/X86/Payload/FMAPayload.hpp @@ -21,9 +21,9 @@ #pragma once -#include "firestarter/Environment/X86/Payload/X86Payload.hpp" +#include "firestarter/X86/Payload/X86Payload.hpp" -namespace firestarter::environment::x86::payload { +namespace firestarter::x86::payload { /// This payload is designed for the FMA CPU extension. class FMAPayload final : public X86Payload { @@ -47,9 +47,9 @@ class FMAPayload final : public X86Payload { /// of the compiled payload. /// \arg PrintAssembler Should the generated assembler code be logged. /// \returns The compiled payload that provides access to the init and load functions. - [[nodiscard]] auto compilePayload(const environment::payload::PayloadSettings& Settings, bool DumpRegisters, + [[nodiscard]] auto compilePayload(const firestarter::payload::PayloadSettings& Settings, bool DumpRegisters, bool ErrorDetection, bool PrintAssembler) const - -> environment::payload::CompiledPayload::UniquePtr override; + -> firestarter::payload::CompiledPayload::UniquePtr override; private: /// Function to initialize the memory used by the high load function. @@ -57,4 +57,4 @@ class FMAPayload final : public X86Payload { /// \arg BufferSize The number of doubles that is allocated in MemoryAddr. void init(double* MemoryAddr, uint64_t BufferSize) const override; }; -} // namespace firestarter::environment::x86::payload +} // namespace firestarter::x86::payload diff --git a/include/firestarter/Environment/X86/Payload/SSE2Payload.hpp b/include/firestarter/X86/Payload/SSE2Payload.hpp similarity index 91% rename from include/firestarter/Environment/X86/Payload/SSE2Payload.hpp rename to include/firestarter/X86/Payload/SSE2Payload.hpp index f6d667be..c685dbbd 100644 --- a/include/firestarter/Environment/X86/Payload/SSE2Payload.hpp +++ b/include/firestarter/X86/Payload/SSE2Payload.hpp @@ -21,9 +21,9 @@ #pragma once -#include "firestarter/Environment/X86/Payload/X86Payload.hpp" +#include "firestarter/X86/Payload/X86Payload.hpp" -namespace firestarter::environment::x86::payload { +namespace firestarter::x86::payload { /// This payload is designed for the SSE2 CPU extension. class SSE2Payload final : public X86Payload { @@ -57,9 +57,9 @@ class SSE2Payload final : public X86Payload { /// of the compiled payload. /// \arg PrintAssembler Should the generated assembler code be logged. /// \returns The compiled payload that provides access to the init and load functions. - [[nodiscard]] auto compilePayload(const environment::payload::PayloadSettings& Settings, bool DumpRegisters, + [[nodiscard]] auto compilePayload(const firestarter::payload::PayloadSettings& Settings, bool DumpRegisters, bool ErrorDetection, bool PrintAssembler) const - -> environment::payload::CompiledPayload::UniquePtr override; + -> firestarter::payload::CompiledPayload::UniquePtr override; private: /// Function to initialize the memory used by the high load function. @@ -67,4 +67,4 @@ class SSE2Payload final : public X86Payload { /// \arg BufferSize The number of doubles that is allocated in MemoryAddr. void init(double* MemoryAddr, uint64_t BufferSize) const override; }; -} // namespace firestarter::environment::x86::payload +} // namespace firestarter::x86::payload diff --git a/include/firestarter/Environment/X86/Payload/X86Payload.hpp b/include/firestarter/X86/Payload/X86Payload.hpp similarity index 98% rename from include/firestarter/Environment/X86/Payload/X86Payload.hpp rename to include/firestarter/X86/Payload/X86Payload.hpp index cfb997f7..18160ba5 100644 --- a/include/firestarter/Environment/X86/Payload/X86Payload.hpp +++ b/include/firestarter/X86/Payload/X86Payload.hpp @@ -23,10 +23,10 @@ #include "firestarter/Constants.hpp" // IWYU pragma: keep #include "firestarter/DumpRegisterStruct.hpp" // IWYU pragma: keep -#include "firestarter/Environment/Payload/Payload.hpp" -#include "firestarter/Environment/X86/X86ProcessorInformation.hpp" #include "firestarter/LoadWorkerMemory.hpp" #include "firestarter/Logging/Log.hpp" // IWYU pragma: keep +#include "firestarter/Payload/Payload.hpp" +#include "firestarter/X86/X86ProcessorInformation.hpp" #include #include @@ -38,9 +38,9 @@ constexpr const auto InitBlocksize = 1024; /// This abstract class models a payload that can be compiled with settings and executed for X86 CPUs. -namespace firestarter::environment::x86::payload { +namespace firestarter::x86::payload { -class X86Payload : public environment::payload::Payload { +class X86Payload : public firestarter::payload::Payload { private: /// This list contains the features (cpu extenstions) that are requied to execute the payload. std::list FeatureRequests; @@ -572,4 +572,4 @@ class X86Payload : public environment::payload::Payload { [[nodiscard]] auto instructionMemory() const -> const auto& { return InstructionMemory; } }; -} // namespace firestarter::environment::x86::payload +} // namespace firestarter::x86::payload diff --git a/include/firestarter/Environment/X86/Payload/ZENFMAPayload.hpp b/include/firestarter/X86/Payload/ZENFMAPayload.hpp similarity index 89% rename from include/firestarter/Environment/X86/Payload/ZENFMAPayload.hpp rename to include/firestarter/X86/Payload/ZENFMAPayload.hpp index 777e6587..648fb0c9 100644 --- a/include/firestarter/Environment/X86/Payload/ZENFMAPayload.hpp +++ b/include/firestarter/X86/Payload/ZENFMAPayload.hpp @@ -21,9 +21,9 @@ #pragma once -#include "firestarter/Environment/X86/Payload/X86Payload.hpp" +#include "firestarter/X86/Payload/X86Payload.hpp" -namespace firestarter::environment::x86::payload { +namespace firestarter::x86::payload { /// This payload is designed for the FMA CPU extension in combination with the first generation Zen microarchitecture. class ZENFMAPayload final : public X86Payload { @@ -42,9 +42,9 @@ class ZENFMAPayload final : public X86Payload { /// of the compiled payload. /// \arg PrintAssembler Should the generated assembler code be logged. /// \returns The compiled payload that provides access to the init and load functions. - [[nodiscard]] auto compilePayload(const environment::payload::PayloadSettings& Settings, bool DumpRegisters, + [[nodiscard]] auto compilePayload(const firestarter::payload::PayloadSettings& Settings, bool DumpRegisters, bool ErrorDetection, bool PrintAssembler) const - -> environment::payload::CompiledPayload::UniquePtr override; + -> firestarter::payload::CompiledPayload::UniquePtr override; private: /// Function to initialize the memory used by the high load function. @@ -52,4 +52,4 @@ class ZENFMAPayload final : public X86Payload { /// \arg BufferSize The number of doubles that is allocated in MemoryAddr. void init(double* MemoryAddr, uint64_t BufferSize) const override; }; -} // namespace firestarter::environment::x86::payload +} // namespace firestarter::x86::payload diff --git a/include/firestarter/Environment/X86/Platform/BulldozerConfig.hpp b/include/firestarter/X86/Platform/BulldozerConfig.hpp similarity index 84% rename from include/firestarter/Environment/X86/Platform/BulldozerConfig.hpp rename to include/firestarter/X86/Platform/BulldozerConfig.hpp index 936b3601..1965d9ef 100644 --- a/include/firestarter/Environment/X86/Platform/BulldozerConfig.hpp +++ b/include/firestarter/X86/Platform/BulldozerConfig.hpp @@ -21,20 +21,20 @@ #pragma once -#include "firestarter/Environment/X86/Payload/FMA4Payload.hpp" -#include "firestarter/Environment/X86/Platform/X86PlatformConfig.hpp" +#include "firestarter/X86/Payload/FMA4Payload.hpp" +#include "firestarter/X86/Platform/X86PlatformConfig.hpp" -namespace firestarter::environment::x86::platform { +namespace firestarter::x86::platform { class BulldozerConfig final : public X86PlatformConfig { public: BulldozerConfig() noexcept : X86PlatformConfig( /*Name=*/"BLD_OPTERON", /*Family=*/21, /*Models=*/{1, 2, 3}, /*Settings=*/ - environment::payload::PayloadSettings( + firestarter::payload::PayloadSettings( /*Threads=*/{1}, /*DataCacheBufferSize=*/{16384, 1048576, 786432}, /*RamBufferSize=*/104857600, /*Lines=*/1536, /*InstructionGroups=*/{{"RAM_L", 1}, {"L3_L", 1}, {"L2_LS", 5}, {"L1_L", 90}, {"REG", 45}}), /*Payload=*/std::make_shared()) {} }; -} // namespace firestarter::environment::x86::platform +} // namespace firestarter::x86::platform diff --git a/include/firestarter/Environment/X86/Platform/HaswellConfig.hpp b/include/firestarter/X86/Platform/HaswellConfig.hpp similarity index 84% rename from include/firestarter/Environment/X86/Platform/HaswellConfig.hpp rename to include/firestarter/X86/Platform/HaswellConfig.hpp index 768d3597..82820a42 100644 --- a/include/firestarter/Environment/X86/Platform/HaswellConfig.hpp +++ b/include/firestarter/X86/Platform/HaswellConfig.hpp @@ -21,20 +21,20 @@ #pragma once -#include "firestarter/Environment/X86/Payload/FMAPayload.hpp" -#include "firestarter/Environment/X86/Platform/X86PlatformConfig.hpp" +#include "firestarter/X86/Payload/FMAPayload.hpp" +#include "firestarter/X86/Platform/X86PlatformConfig.hpp" -namespace firestarter::environment::x86::platform { +namespace firestarter::x86::platform { class HaswellConfig final : public X86PlatformConfig { public: HaswellConfig() noexcept : X86PlatformConfig( /*Name=*/"HSW_COREI", /*Family=*/6, /*Models=*/{60, 61, 69, 70, 71}, /*Settings=*/ - environment::payload::PayloadSettings( + firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 1572864}, /*RamBufferSize=*/104857600, /*Lines=*/1536, /*InstructionGroups=*/{{"RAM_L", 2}, {"L3_LS", 3}, {"L2_LS", 9}, {"L1_LS", 90}, {"REG", 40}}), /*Payload=*/std::make_shared()) {} }; -} // namespace firestarter::environment::x86::platform +} // namespace firestarter::x86::platform diff --git a/include/firestarter/Environment/X86/Platform/HaswellEPConfig.hpp b/include/firestarter/X86/Platform/HaswellEPConfig.hpp similarity index 84% rename from include/firestarter/Environment/X86/Platform/HaswellEPConfig.hpp rename to include/firestarter/X86/Platform/HaswellEPConfig.hpp index 23d2518f..1ff81e64 100644 --- a/include/firestarter/Environment/X86/Platform/HaswellEPConfig.hpp +++ b/include/firestarter/X86/Platform/HaswellEPConfig.hpp @@ -21,20 +21,20 @@ #pragma once -#include "firestarter/Environment/X86/Payload/FMAPayload.hpp" -#include "firestarter/Environment/X86/Platform/X86PlatformConfig.hpp" +#include "firestarter/X86/Payload/FMAPayload.hpp" +#include "firestarter/X86/Platform/X86PlatformConfig.hpp" -namespace firestarter::environment::x86::platform { +namespace firestarter::x86::platform { class HaswellEPConfig final : public X86PlatformConfig { public: HaswellEPConfig() noexcept : X86PlatformConfig( /*Name=*/"HSW_XEONEP", /*Family=*/6, /*Models=*/{63, 79}, /*Settings=*/ - environment::payload::PayloadSettings( + firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 2621440}, /*RamBufferSize=*/104857600, /*Lines=*/1536, /*InstructionGroups=*/{{"RAM_L", 8}, {"L3_LS", 1}, {"L2_LS", 29}, {"L1_LS", 100}, {"REG", 100}}), /*Payload=*/std::make_shared()) {} }; -} // namespace firestarter::environment::x86::platform +} // namespace firestarter::x86::platform diff --git a/include/firestarter/Environment/X86/Platform/KnightsLandingConfig.hpp b/include/firestarter/X86/Platform/KnightsLandingConfig.hpp similarity index 84% rename from include/firestarter/Environment/X86/Platform/KnightsLandingConfig.hpp rename to include/firestarter/X86/Platform/KnightsLandingConfig.hpp index f849c07b..462cdc3b 100644 --- a/include/firestarter/Environment/X86/Platform/KnightsLandingConfig.hpp +++ b/include/firestarter/X86/Platform/KnightsLandingConfig.hpp @@ -21,19 +21,19 @@ #pragma once -#include "firestarter/Environment/X86/Payload/AVX512Payload.hpp" -#include "firestarter/Environment/X86/Platform/X86PlatformConfig.hpp" +#include "firestarter/X86/Payload/AVX512Payload.hpp" +#include "firestarter/X86/Platform/X86PlatformConfig.hpp" -namespace firestarter::environment::x86::platform { +namespace firestarter::x86::platform { class KnightsLandingConfig final : public X86PlatformConfig { public: KnightsLandingConfig() noexcept : X86PlatformConfig(/*Name=*/"KNL_XEONPHI", /*Family=*/6, /*Models=*/{87}, /*Settings=*/ - environment::payload::PayloadSettings( + firestarter::payload::PayloadSettings( /*Threads=*/{4}, /*DataCacheBufferSize=*/{32768, 524288, 236279125}, /*RamBufferSize=*/26214400, /*Lines=*/1536, /*InstructionGroups=*/{{"RAM_P", 3}, {"L2_S", 8}, {"L1_L", 40}, {"REG", 10}}), /*Payload=*/std::make_shared()) {} }; -} // namespace firestarter::environment::x86::platform +} // namespace firestarter::x86::platform diff --git a/include/firestarter/Environment/X86/Platform/NaplesConfig.hpp b/include/firestarter/X86/Platform/NaplesConfig.hpp similarity index 84% rename from include/firestarter/Environment/X86/Platform/NaplesConfig.hpp rename to include/firestarter/X86/Platform/NaplesConfig.hpp index abef11da..7ea5bd0e 100644 --- a/include/firestarter/Environment/X86/Platform/NaplesConfig.hpp +++ b/include/firestarter/X86/Platform/NaplesConfig.hpp @@ -21,20 +21,20 @@ #pragma once -#include "firestarter/Environment/X86/Payload/ZENFMAPayload.hpp" -#include "firestarter/Environment/X86/Platform/X86PlatformConfig.hpp" +#include "firestarter/X86/Payload/ZENFMAPayload.hpp" +#include "firestarter/X86/Platform/X86PlatformConfig.hpp" -namespace firestarter::environment::x86::platform { +namespace firestarter::x86::platform { class NaplesConfig final : public X86PlatformConfig { public: NaplesConfig() noexcept : X86PlatformConfig( /*Name=*/"ZEN_EPYC", /*Family=*/23, /*Models=*/{1, 8, 17, 24}, /*Settings=*/ - environment::payload::PayloadSettings( + firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{65536, 524288, 2097152}, /*RamBufferSize=*/104857600, /*Lines=*/1536, /*InstructionGroups=*/{{"RAM_L", 3}, {"L3_L", 14}, {"L2_L", 75}, {"L1_LS", 81}, {"REG", 100}}), /*Payload=*/std::make_shared()) {} }; -} // namespace firestarter::environment::x86::platform +} // namespace firestarter::x86::platform diff --git a/include/firestarter/Environment/X86/Platform/NehalemConfig.hpp b/include/firestarter/X86/Platform/NehalemConfig.hpp similarity index 83% rename from include/firestarter/Environment/X86/Platform/NehalemConfig.hpp rename to include/firestarter/X86/Platform/NehalemConfig.hpp index 31374061..67ea2dfc 100644 --- a/include/firestarter/Environment/X86/Platform/NehalemConfig.hpp +++ b/include/firestarter/X86/Platform/NehalemConfig.hpp @@ -21,19 +21,19 @@ #pragma once -#include "firestarter/Environment/X86/Payload/SSE2Payload.hpp" -#include "firestarter/Environment/X86/Platform/X86PlatformConfig.hpp" +#include "firestarter/X86/Payload/SSE2Payload.hpp" +#include "firestarter/X86/Platform/X86PlatformConfig.hpp" -namespace firestarter::environment::x86::platform { +namespace firestarter::x86::platform { class NehalemConfig final : public X86PlatformConfig { public: NehalemConfig() noexcept : X86PlatformConfig( /*Name=*/"NHM_COREI", /*Family=*/6, /*Models=*/{30, 37, 23}, /*Settings=*/ - environment::payload::PayloadSettings(/*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 1572864}, + firestarter::payload::PayloadSettings(/*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 1572864}, /*RamBufferSize=*/104857600, /*Lines=*/1536, /*InstructionGroups=*/{{"RAM_P", 1}, {"L1_LS", 70}, {"REG", 2}}), /*Payload=*/std::make_shared()) {} }; -} // namespace firestarter::environment::x86::platform +} // namespace firestarter::x86::platform diff --git a/include/firestarter/Environment/X86/Platform/NehalemEPConfig.hpp b/include/firestarter/X86/Platform/NehalemEPConfig.hpp similarity index 84% rename from include/firestarter/Environment/X86/Platform/NehalemEPConfig.hpp rename to include/firestarter/X86/Platform/NehalemEPConfig.hpp index 9a6a08bb..9ea1641c 100644 --- a/include/firestarter/Environment/X86/Platform/NehalemEPConfig.hpp +++ b/include/firestarter/X86/Platform/NehalemEPConfig.hpp @@ -21,19 +21,19 @@ #pragma once -#include "firestarter/Environment/X86/Payload/SSE2Payload.hpp" -#include "firestarter/Environment/X86/Platform/X86PlatformConfig.hpp" +#include "firestarter/X86/Payload/SSE2Payload.hpp" +#include "firestarter/X86/Platform/X86PlatformConfig.hpp" -namespace firestarter::environment::x86::platform { +namespace firestarter::x86::platform { class NehalemEPConfig final : public X86PlatformConfig { public: NehalemEPConfig() noexcept : X86PlatformConfig(/*Name=*/"NHM_XEONEP", /*Family=*/6, /*Models=*/{26, 44}, /*Settings=*/ - environment::payload::PayloadSettings( + firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 2097152}, /*RamBufferSize=*/104857600, /*Lines=*/1536, /*InstructionGroups=*/{{"RAM_P", 1}, {"L1_LS", 60}, {"REG", 2}}), /*Payload=*/std::make_shared()) {} }; -} // namespace firestarter::environment::x86::platform +} // namespace firestarter::x86::platform diff --git a/include/firestarter/Environment/X86/Platform/RomeConfig.hpp b/include/firestarter/X86/Platform/RomeConfig.hpp similarity index 84% rename from include/firestarter/Environment/X86/Platform/RomeConfig.hpp rename to include/firestarter/X86/Platform/RomeConfig.hpp index e70161d7..189858fb 100644 --- a/include/firestarter/Environment/X86/Platform/RomeConfig.hpp +++ b/include/firestarter/X86/Platform/RomeConfig.hpp @@ -21,21 +21,21 @@ #pragma once -#include "firestarter/Environment/X86/Payload/FMAPayload.hpp" -#include "firestarter/Environment/X86/Platform/X86PlatformConfig.hpp" +#include "firestarter/X86/Payload/FMAPayload.hpp" +#include "firestarter/X86/Platform/X86PlatformConfig.hpp" -namespace firestarter::environment::x86::platform { +namespace firestarter::x86::platform { class RomeConfig final : public X86PlatformConfig { public: RomeConfig() noexcept : X86PlatformConfig( /*Name=*/"ZEN_2_EPYC", /*Family=*/23, /*Models=*/{49}, /*Settings=*/ - environment::payload::PayloadSettings( + firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 524288, 2097152}, /*RamBufferSize=*/104857600, /*Lines=*/1536, /*InstructionGroups=*/ {{"RAM_L", 10}, {"L3_L", 25}, {"L2_L", 91}, {"L1_2LS_256", 72}, {"L1_LS_256", 82}, {"REG", 75}}), /*Payload=*/std::make_shared()) {} }; -} // namespace firestarter::environment::x86::platform +} // namespace firestarter::x86::platform diff --git a/include/firestarter/Environment/X86/Platform/SandyBridgeConfig.hpp b/include/firestarter/X86/Platform/SandyBridgeConfig.hpp similarity index 84% rename from include/firestarter/Environment/X86/Platform/SandyBridgeConfig.hpp rename to include/firestarter/X86/Platform/SandyBridgeConfig.hpp index b5c5b1c4..3198d25b 100644 --- a/include/firestarter/Environment/X86/Platform/SandyBridgeConfig.hpp +++ b/include/firestarter/X86/Platform/SandyBridgeConfig.hpp @@ -21,20 +21,20 @@ #pragma once -#include "firestarter/Environment/X86/Payload/AVXPayload.hpp" -#include "firestarter/Environment/X86/Platform/X86PlatformConfig.hpp" +#include "firestarter/X86/Payload/AVXPayload.hpp" +#include "firestarter/X86/Platform/X86PlatformConfig.hpp" -namespace firestarter::environment::x86::platform { +namespace firestarter::x86::platform { class SandyBridgeConfig final : public X86PlatformConfig { public: SandyBridgeConfig() noexcept : X86PlatformConfig( /*Name=*/"SNB_COREI", /*Family=*/6, /*Models=*/{42, 58}, /*Settings=*/ - environment::payload::PayloadSettings( + firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 1572864}, /*RamBufferSize=*/104857600, /*Lines=*/1536, /*InstructionGroups=*/{{"RAM_L", 2}, {"L3_LS", 4}, {"L2_LS", 10}, {"L1_LS", 90}, {"REG", 45}}), /*Payload=*/std::make_shared()) {} }; -} // namespace firestarter::environment::x86::platform +} // namespace firestarter::x86::platform diff --git a/include/firestarter/Environment/X86/Platform/SandyBridgeEPConfig.hpp b/include/firestarter/X86/Platform/SandyBridgeEPConfig.hpp similarity index 84% rename from include/firestarter/Environment/X86/Platform/SandyBridgeEPConfig.hpp rename to include/firestarter/X86/Platform/SandyBridgeEPConfig.hpp index 67048ba5..bcc96afb 100644 --- a/include/firestarter/Environment/X86/Platform/SandyBridgeEPConfig.hpp +++ b/include/firestarter/X86/Platform/SandyBridgeEPConfig.hpp @@ -21,20 +21,20 @@ #pragma once -#include "firestarter/Environment/X86/Payload/AVXPayload.hpp" -#include "firestarter/Environment/X86/Platform/X86PlatformConfig.hpp" +#include "firestarter/X86/Payload/AVXPayload.hpp" +#include "firestarter/X86/Platform/X86PlatformConfig.hpp" -namespace firestarter::environment::x86::platform { +namespace firestarter::x86::platform { class SandyBridgeEPConfig final : public X86PlatformConfig { public: SandyBridgeEPConfig() noexcept : X86PlatformConfig( /*Name=*/"SNB_XEONEP", /*Family=*/6, /*Models=*/{45, 62}, /*Settings=*/ - environment::payload::PayloadSettings( + firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 2621440}, /*RamBufferSize=*/104857600, /*Lines=*/1536, /*InstructionGroups=*/{{"RAM_L", 3}, {"L3_LS", 2}, {"L2_LS", 10}, {"L1_LS", 90}, {"REG", 30}}), /*Payload=*/std::make_shared()) {} }; -} // namespace firestarter::environment::x86::platform \ No newline at end of file +} // namespace firestarter::x86::platform \ No newline at end of file diff --git a/include/firestarter/Environment/X86/Platform/SkylakeConfig.hpp b/include/firestarter/X86/Platform/SkylakeConfig.hpp similarity index 84% rename from include/firestarter/Environment/X86/Platform/SkylakeConfig.hpp rename to include/firestarter/X86/Platform/SkylakeConfig.hpp index 8a109d11..ed047f72 100644 --- a/include/firestarter/Environment/X86/Platform/SkylakeConfig.hpp +++ b/include/firestarter/X86/Platform/SkylakeConfig.hpp @@ -21,20 +21,20 @@ #pragma once -#include "firestarter/Environment/X86/Payload/FMAPayload.hpp" -#include "firestarter/Environment/X86/Platform/X86PlatformConfig.hpp" +#include "firestarter/X86/Payload/FMAPayload.hpp" +#include "firestarter/X86/Platform/X86PlatformConfig.hpp" -namespace firestarter::environment::x86::platform { +namespace firestarter::x86::platform { class SkylakeConfig final : public X86PlatformConfig { public: SkylakeConfig() noexcept : X86PlatformConfig(/*Name=*/"SKL_COREI", /*Family=*/6, /*Models=*/{78, 94}, /*Settings=*/ - environment::payload::PayloadSettings( + firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 1572864}, /*RamBufferSize=*/104857600, /*Lines=*/1536, /*InstructionGroups=*/ {{"RAM_L", 3}, {"L3_LS_256", 5}, {"L2_LS_256", 18}, {"L1_2LS_256", 78}, {"REG", 40}}), /*Payload=*/std::make_shared()) {} }; -} // namespace firestarter::environment::x86::platform \ No newline at end of file +} // namespace firestarter::x86::platform \ No newline at end of file diff --git a/include/firestarter/Environment/X86/Platform/SkylakeSPConfig.hpp b/include/firestarter/X86/Platform/SkylakeSPConfig.hpp similarity index 88% rename from include/firestarter/Environment/X86/Platform/SkylakeSPConfig.hpp rename to include/firestarter/X86/Platform/SkylakeSPConfig.hpp index 864ebec9..3564e033 100644 --- a/include/firestarter/Environment/X86/Platform/SkylakeSPConfig.hpp +++ b/include/firestarter/X86/Platform/SkylakeSPConfig.hpp @@ -21,16 +21,16 @@ #pragma once -#include "firestarter/Environment/X86/Payload/AVX512Payload.hpp" -#include "firestarter/Environment/X86/Platform/X86PlatformConfig.hpp" +#include "firestarter/X86/Payload/AVX512Payload.hpp" +#include "firestarter/X86/Platform/X86PlatformConfig.hpp" -namespace firestarter::environment::x86::platform { +namespace firestarter::x86::platform { class SkylakeSPConfig final : public X86PlatformConfig { public: SkylakeSPConfig() noexcept : X86PlatformConfig(/*Name=*/"SKL_XEONEP", /*Family=*/6, /*Models=*/{85}, /*Settings=*/ - environment::payload::PayloadSettings(/*Threads=*/{1, 2}, + firestarter::payload::PayloadSettings(/*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 1048576, 1441792}, /*RamBufferSize=*/1048576000, /*Lines=*/1536, /*InstructionGroups=*/ @@ -45,4 +45,4 @@ class SkylakeSPConfig final : public X86PlatformConfig { {"REG", 140}}), /*Payload=*/std::make_shared()) {} }; -} // namespace firestarter::environment::x86::platform +} // namespace firestarter::x86::platform diff --git a/include/firestarter/Environment/X86/Platform/X86PlatformConfig.hpp b/include/firestarter/X86/Platform/X86PlatformConfig.hpp similarity index 88% rename from include/firestarter/Environment/X86/Platform/X86PlatformConfig.hpp rename to include/firestarter/X86/Platform/X86PlatformConfig.hpp index a45078ce..b41faf5d 100644 --- a/include/firestarter/Environment/X86/Platform/X86PlatformConfig.hpp +++ b/include/firestarter/X86/Platform/X86PlatformConfig.hpp @@ -21,14 +21,14 @@ #pragma once -#include "firestarter/Environment/Platform/PlatformConfig.hpp" -#include "firestarter/Environment/ProcessorInformation.hpp" -#include "firestarter/Environment/X86/X86ProcessorInformation.hpp" +#include "firestarter/Platform/PlatformConfig.hpp" +#include "firestarter/ProcessorInformation.hpp" +#include "firestarter/X86/X86ProcessorInformation.hpp" -namespace firestarter::environment::x86::platform { +namespace firestarter::x86::platform { /// Models a platform config that is the default based on x86 CPU family and model ids. -class X86PlatformConfig : public environment::platform::PlatformConfig { +class X86PlatformConfig : public firestarter::platform::PlatformConfig { private: /// The famility id of the processor for which this is the default platform config. unsigned Family; @@ -37,8 +37,8 @@ class X86PlatformConfig : public environment::platform::PlatformConfig { public: X86PlatformConfig(std::string Name, unsigned Family, std::list&& Models, - environment::payload::PayloadSettings&& Settings, - std::shared_ptr&& Payload) noexcept + firestarter::payload::PayloadSettings&& Settings, + std::shared_ptr&& Payload) noexcept : PlatformConfig(std::move(Name), std::move(Settings), std::move(Payload)) , Family(Family) , Models(std::move(Models)) {} @@ -59,7 +59,7 @@ class X86PlatformConfig : public environment::platform::PlatformConfig { /// Clone a the platform config. [[nodiscard]] auto clone() const -> std::unique_ptr final { auto Ptr = std::make_unique(name(), Family, std::list(Models), - environment::payload::PayloadSettings(settings()), + firestarter::payload::PayloadSettings(settings()), std::shared_ptr(payload())); return Ptr; } @@ -80,7 +80,7 @@ class X86PlatformConfig : public environment::platform::PlatformConfig { /// \arg Topology The pointer to the CPUTopology that is used to check agains if this platform is supported. /// \returns true if the platform is supported on the given CPUTopology. [[nodiscard]] auto isAvailable(const ProcessorInformation* Topology) const -> bool final { - return environment::platform::PlatformConfig::isAvailable(Topology); + return firestarter::platform::PlatformConfig::isAvailable(Topology); } /// Check if this platform is available and the default on the current system. This is done by checking if the family @@ -99,4 +99,4 @@ class X86PlatformConfig : public environment::platform::PlatformConfig { } }; -} // namespace firestarter::environment::x86::platform +} // namespace firestarter::x86::platform diff --git a/include/firestarter/Environment/X86/X86Environment.hpp b/include/firestarter/X86/X86Environment.hpp similarity index 75% rename from include/firestarter/Environment/X86/X86Environment.hpp rename to include/firestarter/X86/X86Environment.hpp index 7fb689bd..a9e948fa 100644 --- a/include/firestarter/Environment/X86/X86Environment.hpp +++ b/include/firestarter/X86/X86Environment.hpp @@ -21,22 +21,22 @@ #pragma once -#include "firestarter/Environment/Environment.hpp" -#include "firestarter/Environment/X86/Platform/BulldozerConfig.hpp" -#include "firestarter/Environment/X86/Platform/HaswellConfig.hpp" -#include "firestarter/Environment/X86/Platform/HaswellEPConfig.hpp" -#include "firestarter/Environment/X86/Platform/KnightsLandingConfig.hpp" -#include "firestarter/Environment/X86/Platform/NaplesConfig.hpp" -#include "firestarter/Environment/X86/Platform/NehalemConfig.hpp" -#include "firestarter/Environment/X86/Platform/NehalemEPConfig.hpp" -#include "firestarter/Environment/X86/Platform/RomeConfig.hpp" -#include "firestarter/Environment/X86/Platform/SandyBridgeConfig.hpp" -#include "firestarter/Environment/X86/Platform/SandyBridgeEPConfig.hpp" -#include "firestarter/Environment/X86/Platform/SkylakeConfig.hpp" -#include "firestarter/Environment/X86/Platform/SkylakeSPConfig.hpp" -#include "firestarter/Environment/X86/Platform/X86PlatformConfig.hpp" +#include "firestarter/Environment.hpp" +#include "firestarter/X86/Platform/BulldozerConfig.hpp" +#include "firestarter/X86/Platform/HaswellConfig.hpp" +#include "firestarter/X86/Platform/HaswellEPConfig.hpp" +#include "firestarter/X86/Platform/KnightsLandingConfig.hpp" +#include "firestarter/X86/Platform/NaplesConfig.hpp" +#include "firestarter/X86/Platform/NehalemConfig.hpp" +#include "firestarter/X86/Platform/NehalemEPConfig.hpp" +#include "firestarter/X86/Platform/RomeConfig.hpp" +#include "firestarter/X86/Platform/SandyBridgeConfig.hpp" +#include "firestarter/X86/Platform/SandyBridgeEPConfig.hpp" +#include "firestarter/X86/Platform/SkylakeConfig.hpp" +#include "firestarter/X86/Platform/SkylakeSPConfig.hpp" +#include "firestarter/X86/Platform/X86PlatformConfig.hpp" -namespace firestarter::environment::x86 { +namespace firestarter::x86 { class X86Environment final : public Environment { public: @@ -67,12 +67,12 @@ class X86Environment final : public Environment { } [[nodiscard]] auto platformConfigs() const - -> const std::vector>& override { + -> const std::vector>& override { return PlatformConfigs; } [[nodiscard]] auto fallbackPlatformConfigs() const - -> const std::vector>& override { + -> const std::vector>& override { return FallbackPlatformConfigs; } @@ -80,7 +80,7 @@ class X86Environment final : public Environment { /// The list of availabe platform configs that is printed when supplying the --avail command line argument. The IDs /// for these configs are generated by iterating through this list starting with 1. To maintain stable IDs in /// FIRESTARTER new configs should be added to the bottom of the list. - const std::vector> PlatformConfigs = { + const std::vector> PlatformConfigs = { std::make_shared(), std::make_shared(), std::make_shared(), std::make_shared(), std::make_shared(), std::make_shared(), @@ -94,7 +94,7 @@ class X86Environment final : public Environment { /// therefore it is the last on the list. CPUs that support AVX512 will most certainly also support FMA and AVX, /// AVX512 takes precedence. This list should contain one entry for each of the supported CPU extensions by the /// FIRESTARTER payloads. - const std::vector> FallbackPlatformConfigs = { + const std::vector> FallbackPlatformConfigs = { std::make_shared(), // AVX512 std::make_shared(), // FMA4 std::make_shared(), // FMA @@ -103,4 +103,4 @@ class X86Environment final : public Environment { }; }; -} // namespace firestarter::environment::x86 +} // namespace firestarter::x86 diff --git a/include/firestarter/Environment/X86/X86ProcessorInformation.hpp b/include/firestarter/X86/X86ProcessorInformation.hpp similarity index 96% rename from include/firestarter/Environment/X86/X86ProcessorInformation.hpp rename to include/firestarter/X86/X86ProcessorInformation.hpp index 60b924b4..3acda6da 100644 --- a/include/firestarter/Environment/X86/X86ProcessorInformation.hpp +++ b/include/firestarter/X86/X86ProcessorInformation.hpp @@ -21,11 +21,11 @@ #pragma once -#include "firestarter/Environment/ProcessorInformation.hpp" +#include "firestarter/ProcessorInformation.hpp" #include -namespace firestarter::environment::x86 { +namespace firestarter::x86 { /// This class models the properties of a x86_64 processor. class X86ProcessorInformation final : public ProcessorInformation { @@ -85,4 +85,4 @@ inline auto operator<<(std::ostream& Stream, X86ProcessorInformation const& CpuT return CpuTopology.print(Stream); } -} // namespace firestarter::environment::x86 \ No newline at end of file +} // namespace firestarter::x86 \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aa0930cd..c8b07886 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,28 +6,27 @@ add_library(firestartercore STATIC firestarter/DumpRegisterWorker.cpp firestarter/CPUTopology.cpp firestarter/ThreadAffinity.cpp + firestarter/Environment.cpp + firestarter/ProcessorInformation.cpp firestarter/Config/Config.cpp firestarter/Config/CpuBind.cpp - - firestarter/Environment/Environment.cpp - firestarter/Environment/ProcessorInformation.cpp - firestarter/Environment/Payload/CompiledPayload.cpp - firestarter/Environment/Payload/PayloadSettings.cpp + firestarter/Payload/CompiledPayload.cpp + firestarter/Payload/PayloadSettings.cpp # here starts the x86 specific code - firestarter/Environment/X86/X86ProcessorInformation.cpp - - firestarter/Environment/X86/Platform/X86PlatformConfig.cpp - - firestarter/Environment/X86/Payload/X86Payload.cpp - firestarter/Environment/X86/Payload/AVX512Payload.cpp - firestarter/Environment/X86/Payload/FMA4Payload.cpp - firestarter/Environment/X86/Payload/FMAPayload.cpp - firestarter/Environment/X86/Payload/ZENFMAPayload.cpp - firestarter/Environment/X86/Payload/AVXPayload.cpp - firestarter/Environment/X86/Payload/SSE2Payload.cpp + firestarter/X86/X86ProcessorInformation.cpp + + firestarter/X86/Platform/X86PlatformConfig.cpp + + firestarter/X86/Payload/X86Payload.cpp + firestarter/X86/Payload/AVX512Payload.cpp + firestarter/X86/Payload/FMA4Payload.cpp + firestarter/X86/Payload/FMAPayload.cpp + firestarter/X86/Payload/ZENFMAPayload.cpp + firestarter/X86/Payload/AVXPayload.cpp + firestarter/X86/Payload/SSE2Payload.cpp ) target_link_libraries(firestartercore diff --git a/src/firestarter/Environment/Environment.cpp b/src/firestarter/Environment.cpp similarity index 98% rename from src/firestarter/Environment/Environment.cpp rename to src/firestarter/Environment.cpp index 5a178250..380fa138 100644 --- a/src/firestarter/Environment/Environment.cpp +++ b/src/firestarter/Environment.cpp @@ -19,7 +19,7 @@ * Contact: daniel.hackenberg@tu-dresden.de *****************************************************************************/ -#include "firestarter/Environment/Environment.hpp" +#include "firestarter/Environment.hpp" #include "firestarter/Logging/Log.hpp" #include @@ -27,7 +27,7 @@ #include #include -namespace firestarter::environment { +namespace firestarter { void Environment::selectFunction(std::optional FunctionId, const CPUTopology& Topology, bool AllowUnavailablePayload) { @@ -197,4 +197,4 @@ void Environment::printFunctionSummary(bool ForceYes) const { } } -} // namespace firestarter::environment \ No newline at end of file +} // namespace firestarter \ No newline at end of file diff --git a/src/firestarter/Firestarter.cpp b/src/firestarter/Firestarter.cpp index 05d5acfe..1b42870d 100644 --- a/src/firestarter/Firestarter.cpp +++ b/src/firestarter/Firestarter.cpp @@ -20,12 +20,12 @@ *****************************************************************************/ #include "firestarter/Firestarter.hpp" -#include "firestarter/Environment/X86/X86Environment.hpp" #include "firestarter/Logging/Log.hpp" #include "firestarter/Measurement/Metric/IPCEstimate.hpp" #include "firestarter/Optimizer/Algorithm/NSGA2.hpp" #include "firestarter/Optimizer/History.hpp" #include "firestarter/Optimizer/Problem/CLIArgumentProblem.hpp" +#include "firestarter/X86/X86Environment.hpp" #include #include @@ -37,7 +37,7 @@ Firestarter::Firestarter(Config&& ProvidedConfig) : Cfg(std::move(ProvidedConfig)) , Topology(std::make_unique()) { if constexpr (firestarter::OptionalFeatures.IsX86) { - Environment = std::make_unique(); + EnvironmentPtr = std::make_unique(); } const auto Affinity = @@ -46,7 +46,7 @@ Firestarter::Firestarter(Config&& ProvidedConfig) if constexpr (firestarter::OptionalFeatures.IsX86) { // Error detection uses crc32 instruction added by the SSE4.2 extension to x86 if (Cfg.ErrorDetection) { - const auto& X86Env = *dynamic_cast(Environment.get()); + const auto& X86Env = *dynamic_cast(EnvironmentPtr.get()); if (!X86Env.processorInfos().featuresAsmjit().has(asmjit::CpuFeatures::X86::kSSE4_2)) { throw std::invalid_argument("Option --error-detection requires the crc32 " "instruction added with SSE_4_2.\n"); @@ -61,23 +61,23 @@ Firestarter::Firestarter(Config&& ProvidedConfig) } if (Cfg.PrintFunctionSummary) { - Environment->printFunctionSummary(/*ForceYes=*/false); + EnvironmentPtr->printFunctionSummary(/*ForceYes=*/false); safeExit(EXIT_SUCCESS); } - Environment->selectFunction(Cfg.FunctionId, *Topology, Cfg.AllowUnavailablePayload); + EnvironmentPtr->selectFunction(Cfg.FunctionId, *Topology, Cfg.AllowUnavailablePayload); if (Cfg.ListInstructionGroups) { - Environment->printAvailableInstructionGroups(); + EnvironmentPtr->printAvailableInstructionGroups(); safeExit(EXIT_SUCCESS); } if (!Cfg.InstructionGroups.empty()) { - Environment->selectInstructionGroups(Cfg.InstructionGroups); + EnvironmentPtr->selectInstructionGroups(Cfg.InstructionGroups); } if (Cfg.LineCount != 0) { - Environment->setLineCount(Cfg.LineCount); + EnvironmentPtr->setLineCount(Cfg.LineCount); } if constexpr (firestarter::OptionalFeatures.OptimizationEnabled) { @@ -152,7 +152,7 @@ Firestarter::Firestarter(Config&& ProvidedConfig) auto Prob = std::make_shared( std::move(ApplySettings), MeasurementWorker, Cfg.OptimizationMetrics, Cfg.EvaluationDuration, Cfg.StartDelta, - Cfg.StopDelta, Environment->config().settings().instructionGroupItems()); + Cfg.StopDelta, EnvironmentPtr->config().settings().instructionGroupItems()); Population = std::make_unique(std::move(Prob)); @@ -167,14 +167,14 @@ Firestarter::Firestarter(Config&& ProvidedConfig) } } - Environment->printSelectedCodePathSummary(); + EnvironmentPtr->printSelectedCodePathSummary(); { std::stringstream Ss; Topology->printSystemSummary(Ss); Ss << "\n"; - Ss << Environment->processorInfos(); + Ss << EnvironmentPtr->processorInfos(); Topology->printCacheSummary(Ss); log::info() << Ss.str(); @@ -229,7 +229,7 @@ void Firestarter::mainThread() { Firestarter::Optimizer->join(); Firestarter::Optimizer.reset(); - auto PayloadItems = Environment->config().settings().instructionGroupItems(); + auto PayloadItems = EnvironmentPtr->config().settings().instructionGroupItems(); firestarter::optimizer::History::save(Cfg.OptimizeOutfile, StartTime, PayloadItems, Cfg.Argc, Cfg.Argv); diff --git a/src/firestarter/LoadWorker.cpp b/src/firestarter/LoadWorker.cpp index 81824c3a..e1cc2342 100644 --- a/src/firestarter/LoadWorker.cpp +++ b/src/firestarter/LoadWorker.cpp @@ -71,7 +71,7 @@ void Firestarter::initLoadWorkers(const ThreadAffinity& Affinity) { } for (uint64_t I = 0; I < Affinity.RequestedNumThreads; I++) { - auto Td = std::make_shared(I, Affinity.CpuBind[I], std::cref(*Environment), std::cref(*Topology), + auto Td = std::make_shared(I, Affinity.CpuBind[I], std::cref(*EnvironmentPtr), std::cref(*Topology), std::ref(LoadVar), Cfg.Period, Cfg.DumpRegisters, Cfg.ErrorDetection); if (Cfg.ErrorDetection) { @@ -193,7 +193,7 @@ void Firestarter::printPerformanceReport() { } double const Runtime = static_cast(StopTimestamp - StartTimestamp) / - static_cast(Environment->processorInfos().clockrate()); + static_cast(EnvironmentPtr->processorInfos().clockrate()); double const GFlops = static_cast(LoadThreads.front().second->CompiledPayloadPtr->stats().Flops) * 0.000000001 * static_cast(Iterations) / Runtime; double const Bandwidth = static_cast(LoadThreads.front().second->CompiledPayloadPtr->stats().Bytes) * diff --git a/src/firestarter/Environment/Payload/CompiledPayload.cpp b/src/firestarter/Payload/CompiledPayload.cpp similarity index 85% rename from src/firestarter/Environment/Payload/CompiledPayload.cpp rename to src/firestarter/Payload/CompiledPayload.cpp index 33183d7a..596332ff 100644 --- a/src/firestarter/Environment/Payload/CompiledPayload.cpp +++ b/src/firestarter/Payload/CompiledPayload.cpp @@ -19,10 +19,10 @@ * Contact: daniel.hackenberg@tu-dresden.de *****************************************************************************/ -#include "firestarter/Environment/Payload/CompiledPayload.hpp" -#include "firestarter/Environment/Payload/Payload.hpp" +#include "firestarter/Payload/CompiledPayload.hpp" +#include "firestarter/Payload/Payload.hpp" -namespace firestarter::environment::payload { +namespace firestarter::payload { void CompiledPayload::init(double* MemoryAddr, uint64_t BufferSize) { PayloadPtr->init(MemoryAddr, BufferSize); } @@ -30,4 +30,4 @@ void CompiledPayload::lowLoadFunction(volatile LoadThreadWorkType& LoadVar, std: PayloadPtr->lowLoadFunction(LoadVar, Period); }; -}; // namespace firestarter::environment::payload \ No newline at end of file +}; // namespace firestarter::payload \ No newline at end of file diff --git a/src/firestarter/Environment/Payload/PayloadSettings.cpp b/src/firestarter/Payload/PayloadSettings.cpp similarity index 95% rename from src/firestarter/Environment/Payload/PayloadSettings.cpp rename to src/firestarter/Payload/PayloadSettings.cpp index 25ca4ea4..12d8f41a 100644 --- a/src/firestarter/Environment/Payload/PayloadSettings.cpp +++ b/src/firestarter/Payload/PayloadSettings.cpp @@ -19,12 +19,12 @@ * Contact: daniel.hackenberg@tu-dresden.de *****************************************************************************/ -#include "firestarter/Environment/Payload/PayloadSettings.hpp" +#include "firestarter/Payload/PayloadSettings.hpp" #include #include -namespace firestarter::environment::payload { +namespace firestarter::payload { auto PayloadSettings::getSequenceStartCount(const std::vector& Sequence, const std::string& Start) -> unsigned { @@ -95,4 +95,4 @@ auto PayloadSettings::getRAMLoopCount(const std::vector& Sequence, (1.0 * Size / 64 / (getRAMSequenceCount(Sequence) * getNumberOfSequenceRepetitions(Sequence, NumberOfLines)))); } -}; // namespace firestarter::environment::payload \ No newline at end of file +}; // namespace firestarter::payload \ No newline at end of file diff --git a/src/firestarter/Environment/ProcessorInformation.cpp b/src/firestarter/ProcessorInformation.cpp similarity index 97% rename from src/firestarter/Environment/ProcessorInformation.cpp rename to src/firestarter/ProcessorInformation.cpp index 9f99daa7..c7c9c115 100644 --- a/src/firestarter/Environment/ProcessorInformation.cpp +++ b/src/firestarter/ProcessorInformation.cpp @@ -19,7 +19,7 @@ * Contact: daniel.hackenberg@tu-dresden.de *****************************************************************************/ -#include "firestarter/Environment/ProcessorInformation.hpp" +#include "firestarter/ProcessorInformation.hpp" #include "firestarter/Logging/Log.hpp" #include @@ -30,7 +30,7 @@ #include #endif -namespace firestarter::environment { +namespace firestarter { auto ProcessorInformation::print(std::ostream& Stream) const -> std::ostream& { std::stringstream Ss; @@ -188,4 +188,4 @@ auto ProcessorInformation::scalingGovernor() -> std::string { return getFileAsStream("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor").str(); } -}; // namespace firestarter::environment \ No newline at end of file +}; // namespace firestarter \ No newline at end of file diff --git a/src/firestarter/Environment/X86/Payload/AVX512Payload.cpp b/src/firestarter/X86/Payload/AVX512Payload.cpp similarity index 94% rename from src/firestarter/Environment/X86/Payload/AVX512Payload.cpp rename to src/firestarter/X86/Payload/AVX512Payload.cpp index 88d02440..6ddc3a8f 100644 --- a/src/firestarter/Environment/X86/Payload/AVX512Payload.cpp +++ b/src/firestarter/X86/Payload/AVX512Payload.cpp @@ -19,14 +19,14 @@ * Contact: daniel.hackenberg@tu-dresden.de *****************************************************************************/ -#include "firestarter/Environment/X86/Payload/AVX512Payload.hpp" -#include "firestarter/Environment/X86/Payload/CompiledX86Payload.hpp" +#include "firestarter/X86/Payload/AVX512Payload.hpp" +#include "firestarter/X86/Payload/CompiledX86Payload.hpp" -namespace firestarter::environment::x86::payload { +namespace firestarter::x86::payload { -auto AVX512Payload::compilePayload(const environment::payload::PayloadSettings& Settings, bool DumpRegisters, +auto AVX512Payload::compilePayload(const firestarter::payload::PayloadSettings& Settings, bool DumpRegisters, bool ErrorDetection, bool PrintAssembler) const - -> environment::payload::CompiledPayload::UniquePtr { + -> firestarter::payload::CompiledPayload::UniquePtr { using Imm = asmjit::Imm; using Zmm = asmjit::x86::Zmm; // NOLINTBEGIN(readability-identifier-naming) @@ -40,10 +40,10 @@ auto AVX512Payload::compilePayload(const environment::payload::PayloadSettings& // to reach the desired size auto Sequence = Settings.sequence(); auto Repetitions = - environment::payload::PayloadSettings::getNumberOfSequenceRepetitions(Sequence, Settings.linesPerThread()); + firestarter::payload::PayloadSettings::getNumberOfSequenceRepetitions(Sequence, Settings.linesPerThread()); // compute count of flops and memory access for performance report - environment::payload::PayloadStats Stats; + firestarter::payload::PayloadStats Stats; for (const auto& Item : Sequence) { auto It = instructionFlops().find(Item); @@ -78,11 +78,11 @@ auto AVX512Payload::compilePayload(const environment::payload::PayloadSettings& // calculate the reset counters for the buffers const auto L2LoopCount = - environment::payload::PayloadSettings::getL2LoopCount(Sequence, Settings.linesPerThread(), L2Size); + firestarter::payload::PayloadSettings::getL2LoopCount(Sequence, Settings.linesPerThread(), L2Size); const auto L3LoopCount = - environment::payload::PayloadSettings::getL3LoopCount(Sequence, Settings.linesPerThread(), L3Size); + firestarter::payload::PayloadSettings::getL3LoopCount(Sequence, Settings.linesPerThread(), L3Size); const auto RamLoopCount = - environment::payload::PayloadSettings::getRAMLoopCount(Sequence, Settings.linesPerThread(), RamSize); + firestarter::payload::PayloadSettings::getRAMLoopCount(Sequence, Settings.linesPerThread(), RamSize); asmjit::CodeHolder Code; Code.init(asmjit::Environment::host()); @@ -303,7 +303,7 @@ auto AVX512Payload::compilePayload(const environment::payload::PayloadSettings& } Cb.movq(TempReg, IterReg); // restore iteration counter - if (environment::payload::PayloadSettings::getRAMSequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getRAMSequenceCount(Sequence) > 0) { // reset RAM counter auto NoRamReset = Cb.newLabel(); @@ -317,7 +317,7 @@ auto AVX512Payload::compilePayload(const environment::payload::PayloadSettings& Stats.Instructions += 2; } Cb.inc(TempReg); // increment iteration counter - if (environment::payload::PayloadSettings::getL2SequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getL2SequenceCount(Sequence) > 0) { // reset L2-Cache counter auto NoL2Reset = Cb.newLabel(); @@ -331,7 +331,7 @@ auto AVX512Payload::compilePayload(const environment::payload::PayloadSettings& Stats.Instructions += 2; } Cb.movq(IterReg, TempReg); // store iteration counter - if (environment::payload::PayloadSettings::getL3SequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getL3SequenceCount(Sequence) > 0) { // reset L3-Cache counter auto NoL3Reset = Cb.newLabel(); @@ -393,4 +393,4 @@ void AVX512Payload::init(double* MemoryAddr, uint64_t BufferSize) const { X86Payload::initMemory(MemoryAddr, BufferSize, 0.27948995982e-4, 0.27948995982e-4); } -} // namespace firestarter::environment::x86::payload \ No newline at end of file +} // namespace firestarter::x86::payload \ No newline at end of file diff --git a/src/firestarter/Environment/X86/Payload/AVXPayload.cpp b/src/firestarter/X86/Payload/AVXPayload.cpp similarity index 94% rename from src/firestarter/Environment/X86/Payload/AVXPayload.cpp rename to src/firestarter/X86/Payload/AVXPayload.cpp index 82ded951..a403acd1 100644 --- a/src/firestarter/Environment/X86/Payload/AVXPayload.cpp +++ b/src/firestarter/X86/Payload/AVXPayload.cpp @@ -19,14 +19,14 @@ * Contact: daniel.hackenberg@tu-dresden.de *****************************************************************************/ -#include "firestarter/Environment/X86/Payload/AVXPayload.hpp" -#include "firestarter/Environment/X86/Payload/CompiledX86Payload.hpp" +#include "firestarter/X86/Payload/AVXPayload.hpp" +#include "firestarter/X86/Payload/CompiledX86Payload.hpp" -namespace firestarter::environment::x86::payload { +namespace firestarter::x86::payload { -auto AVXPayload::compilePayload(const environment::payload::PayloadSettings& Settings, bool DumpRegisters, +auto AVXPayload::compilePayload(const firestarter::payload::PayloadSettings& Settings, bool DumpRegisters, bool ErrorDetection, bool PrintAssembler) const - -> environment::payload::CompiledPayload::UniquePtr { + -> firestarter::payload::CompiledPayload::UniquePtr { using Imm = asmjit::Imm; using Mm = asmjit::x86::Mm; using Xmm = asmjit::x86::Xmm; @@ -38,10 +38,10 @@ auto AVXPayload::compilePayload(const environment::payload::PayloadSettings& Set // to reach the desired size auto Sequence = Settings.sequence(); auto Repetitions = - environment::payload::PayloadSettings::getNumberOfSequenceRepetitions(Sequence, Settings.linesPerThread()); + firestarter::payload::PayloadSettings::getNumberOfSequenceRepetitions(Sequence, Settings.linesPerThread()); // compute count of flops and memory access for performance report - environment::payload::PayloadStats Stats; + firestarter::payload::PayloadStats Stats; for (const auto& Item : Sequence) { auto It = instructionFlops().find(Item); @@ -76,11 +76,11 @@ auto AVXPayload::compilePayload(const environment::payload::PayloadSettings& Set // calculate the reset counters for the buffers const auto L2LoopCount = - environment::payload::PayloadSettings::getL2LoopCount(Sequence, Settings.linesPerThread(), L2Size); + firestarter::payload::PayloadSettings::getL2LoopCount(Sequence, Settings.linesPerThread(), L2Size); const auto L3LoopCount = - environment::payload::PayloadSettings::getL3LoopCount(Sequence, Settings.linesPerThread(), L3Size); + firestarter::payload::PayloadSettings::getL3LoopCount(Sequence, Settings.linesPerThread(), L3Size); const auto RamLoopCount = - environment::payload::PayloadSettings::getRAMLoopCount(Sequence, Settings.linesPerThread(), RamSize); + firestarter::payload::PayloadSettings::getRAMLoopCount(Sequence, Settings.linesPerThread(), RamSize); asmjit::CodeHolder Code; Code.init(asmjit::Environment::host()); @@ -334,7 +334,7 @@ auto AVXPayload::compilePayload(const environment::payload::PayloadSettings& Set } } - if (environment::payload::PayloadSettings::getRAMSequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getRAMSequenceCount(Sequence) > 0) { // reset RAM counter auto NoRamReset = Cb.newLabel(); @@ -347,7 +347,7 @@ auto AVXPayload::compilePayload(const environment::payload::PayloadSettings& Set // adds always two instruction Stats.Instructions += 2; } - if (environment::payload::PayloadSettings::getL2SequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getL2SequenceCount(Sequence) > 0) { // reset L2-Cache counter auto NoL2Reset = Cb.newLabel(); @@ -360,7 +360,7 @@ auto AVXPayload::compilePayload(const environment::payload::PayloadSettings& Set // adds always two instruction Stats.Instructions += 2; } - if (environment::payload::PayloadSettings::getL3SequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getL3SequenceCount(Sequence) > 0) { // reset L3-Cache counter auto NoL3Reset = Cb.newLabel(); @@ -423,4 +423,4 @@ void AVXPayload::init(double* MemoryAddr, uint64_t BufferSize) const { X86Payload::initMemory(MemoryAddr, BufferSize, 1.654738925401e-10, 1.654738925401e-15); } -} // namespace firestarter::environment::x86::payload \ No newline at end of file +} // namespace firestarter::x86::payload \ No newline at end of file diff --git a/src/firestarter/Environment/X86/Payload/FMA4Payload.cpp b/src/firestarter/X86/Payload/FMA4Payload.cpp similarity index 94% rename from src/firestarter/Environment/X86/Payload/FMA4Payload.cpp rename to src/firestarter/X86/Payload/FMA4Payload.cpp index 91f3479a..9344212d 100644 --- a/src/firestarter/Environment/X86/Payload/FMA4Payload.cpp +++ b/src/firestarter/X86/Payload/FMA4Payload.cpp @@ -19,14 +19,14 @@ * Contact: daniel.hackenberg@tu-dresden.de *****************************************************************************/ -#include "firestarter/Environment/X86/Payload/FMA4Payload.hpp" -#include "firestarter/Environment/X86/Payload/CompiledX86Payload.hpp" +#include "firestarter/X86/Payload/FMA4Payload.hpp" +#include "firestarter/X86/Payload/CompiledX86Payload.hpp" -namespace firestarter::environment::x86::payload { +namespace firestarter::x86::payload { -auto FMA4Payload::compilePayload(const environment::payload::PayloadSettings& Settings, bool DumpRegisters, +auto FMA4Payload::compilePayload(const firestarter::payload::PayloadSettings& Settings, bool DumpRegisters, bool ErrorDetection, bool PrintAssembler) const - -> environment::payload::CompiledPayload::UniquePtr { + -> firestarter::payload::CompiledPayload::UniquePtr { using Imm = asmjit::Imm; using Xmm = asmjit::x86::Xmm; // NOLINTBEGIN(readability-identifier-naming) @@ -39,10 +39,10 @@ auto FMA4Payload::compilePayload(const environment::payload::PayloadSettings& Se // to reach the desired size auto Sequence = Settings.sequence(); auto Repetitions = - environment::payload::PayloadSettings::getNumberOfSequenceRepetitions(Sequence, Settings.linesPerThread()); + firestarter::payload::PayloadSettings::getNumberOfSequenceRepetitions(Sequence, Settings.linesPerThread()); // compute count of flops and memory access for performance report - environment::payload::PayloadStats Stats; + firestarter::payload::PayloadStats Stats; for (const auto& Item : Sequence) { auto It = instructionFlops().find(Item); @@ -77,11 +77,11 @@ auto FMA4Payload::compilePayload(const environment::payload::PayloadSettings& Se // calculate the reset counters for the buffers const auto L2LoopCount = - environment::payload::PayloadSettings::getL2LoopCount(Sequence, Settings.linesPerThread(), L2Size); + firestarter::payload::PayloadSettings::getL2LoopCount(Sequence, Settings.linesPerThread(), L2Size); const auto L3LoopCount = - environment::payload::PayloadSettings::getL3LoopCount(Sequence, Settings.linesPerThread(), L3Size); + firestarter::payload::PayloadSettings::getL3LoopCount(Sequence, Settings.linesPerThread(), L3Size); const auto RamLoopCount = - environment::payload::PayloadSettings::getRAMLoopCount(Sequence, Settings.linesPerThread(), RamSize); + firestarter::payload::PayloadSettings::getRAMLoopCount(Sequence, Settings.linesPerThread(), RamSize); asmjit::CodeHolder Code; Code.init(asmjit::Environment::host()); @@ -305,7 +305,7 @@ auto FMA4Payload::compilePayload(const environment::payload::PayloadSettings& Se } Cb.movq(TempReg, IterReg); // restore iteration counter - if (environment::payload::PayloadSettings::getRAMSequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getRAMSequenceCount(Sequence) > 0) { // reset RAM counter auto NoRamReset = Cb.newLabel(); @@ -319,7 +319,7 @@ auto FMA4Payload::compilePayload(const environment::payload::PayloadSettings& Se Stats.Instructions += 2; } Cb.inc(TempReg); // increment iteration counter - if (environment::payload::PayloadSettings::getL2SequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getL2SequenceCount(Sequence) > 0) { // reset L2-Cache counter auto NoL2Reset = Cb.newLabel(); @@ -333,7 +333,7 @@ auto FMA4Payload::compilePayload(const environment::payload::PayloadSettings& Se Stats.Instructions += 2; } Cb.movq(IterReg, TempReg); // store iteration counter - if (environment::payload::PayloadSettings::getL3SequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getL3SequenceCount(Sequence) > 0) { // reset L3-Cache counter auto NoL3Reset = Cb.newLabel(); @@ -396,4 +396,4 @@ void FMA4Payload::init(double* MemoryAddr, uint64_t BufferSize) const { X86Payload::initMemory(MemoryAddr, BufferSize, 0.27948995982e-4, 0.27948995982e-4); } -} // namespace firestarter::environment::x86::payload \ No newline at end of file +} // namespace firestarter::x86::payload \ No newline at end of file diff --git a/src/firestarter/Environment/X86/Payload/FMAPayload.cpp b/src/firestarter/X86/Payload/FMAPayload.cpp similarity index 94% rename from src/firestarter/Environment/X86/Payload/FMAPayload.cpp rename to src/firestarter/X86/Payload/FMAPayload.cpp index 03b8995c..86953aa3 100644 --- a/src/firestarter/Environment/X86/Payload/FMAPayload.cpp +++ b/src/firestarter/X86/Payload/FMAPayload.cpp @@ -19,14 +19,14 @@ * Contact: daniel.hackenberg@tu-dresden.de *****************************************************************************/ -#include "firestarter/Environment/X86/Payload/FMAPayload.hpp" -#include "firestarter/Environment/X86/Payload/CompiledX86Payload.hpp" +#include "firestarter/X86/Payload/FMAPayload.hpp" +#include "firestarter/X86/Payload/CompiledX86Payload.hpp" -namespace firestarter::environment::x86::payload { +namespace firestarter::x86::payload { -auto FMAPayload::compilePayload(const environment::payload::PayloadSettings& Settings, bool DumpRegisters, +auto FMAPayload::compilePayload(const firestarter::payload::PayloadSettings& Settings, bool DumpRegisters, bool ErrorDetection, bool PrintAssembler) const - -> environment::payload::CompiledPayload::UniquePtr { + -> firestarter::payload::CompiledPayload::UniquePtr { using Imm = asmjit::Imm; using Xmm = asmjit::x86::Xmm; using Ymm = asmjit::x86::Ymm; @@ -41,10 +41,10 @@ auto FMAPayload::compilePayload(const environment::payload::PayloadSettings& Set // to reach the desired size auto Sequence = Settings.sequence(); auto Repetitions = - environment::payload::PayloadSettings::getNumberOfSequenceRepetitions(Sequence, Settings.linesPerThread()); + firestarter::payload::PayloadSettings::getNumberOfSequenceRepetitions(Sequence, Settings.linesPerThread()); // compute count of flops and memory access for performance report - environment::payload::PayloadStats Stats; + firestarter::payload::PayloadStats Stats; for (const auto& Item : Sequence) { auto It = instructionFlops().find(Item); @@ -79,11 +79,11 @@ auto FMAPayload::compilePayload(const environment::payload::PayloadSettings& Set // calculate the reset counters for the buffers const auto L2LoopCount = - environment::payload::PayloadSettings::getL2LoopCount(Sequence, Settings.linesPerThread(), L2Size); + firestarter::payload::PayloadSettings::getL2LoopCount(Sequence, Settings.linesPerThread(), L2Size); const auto L3LoopCount = - environment::payload::PayloadSettings::getL3LoopCount(Sequence, Settings.linesPerThread(), L3Size); + firestarter::payload::PayloadSettings::getL3LoopCount(Sequence, Settings.linesPerThread(), L3Size); const auto RamLoopCount = - environment::payload::PayloadSettings::getRAMLoopCount(Sequence, Settings.linesPerThread(), RamSize); + firestarter::payload::PayloadSettings::getRAMLoopCount(Sequence, Settings.linesPerThread(), RamSize); asmjit::CodeHolder Code; Code.init(asmjit::Environment::host()); @@ -341,7 +341,7 @@ auto FMAPayload::compilePayload(const environment::payload::PayloadSettings& Set } Cb.movq(TempReg, IterReg); // restore iteration counter - if (environment::payload::PayloadSettings::getRAMSequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getRAMSequenceCount(Sequence) > 0) { // reset RAM counter auto NoRamReset = Cb.newLabel(); @@ -355,7 +355,7 @@ auto FMAPayload::compilePayload(const environment::payload::PayloadSettings& Set Stats.Instructions += 2; } Cb.inc(TempReg); // increment iteration counter - if (environment::payload::PayloadSettings::getL2SequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getL2SequenceCount(Sequence) > 0) { // reset L2-Cache counter auto NoL2Reset = Cb.newLabel(); @@ -369,7 +369,7 @@ auto FMAPayload::compilePayload(const environment::payload::PayloadSettings& Set Stats.Instructions += 2; } Cb.movq(IterReg, TempReg); // store iteration counter - if (environment::payload::PayloadSettings::getL3SequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getL3SequenceCount(Sequence) > 0) { // reset L3-Cache counter auto NoL3Reset = Cb.newLabel(); @@ -431,4 +431,4 @@ void FMAPayload::init(double* MemoryAddr, uint64_t BufferSize) const { X86Payload::initMemory(MemoryAddr, BufferSize, 0.27948995982e-4, 0.27948995982e-4); } -} // namespace firestarter::environment::x86::payload \ No newline at end of file +} // namespace firestarter::x86::payload \ No newline at end of file diff --git a/src/firestarter/Environment/X86/Payload/SSE2Payload.cpp b/src/firestarter/X86/Payload/SSE2Payload.cpp similarity index 94% rename from src/firestarter/Environment/X86/Payload/SSE2Payload.cpp rename to src/firestarter/X86/Payload/SSE2Payload.cpp index 8f443781..076f7083 100644 --- a/src/firestarter/Environment/X86/Payload/SSE2Payload.cpp +++ b/src/firestarter/X86/Payload/SSE2Payload.cpp @@ -19,14 +19,14 @@ * Contact: daniel.hackenberg@tu-dresden.de *****************************************************************************/ -#include "firestarter/Environment/X86/Payload/SSE2Payload.hpp" -#include "firestarter/Environment/X86/Payload/CompiledX86Payload.hpp" +#include "firestarter/X86/Payload/SSE2Payload.hpp" +#include "firestarter/X86/Payload/CompiledX86Payload.hpp" -namespace firestarter::environment::x86::payload { +namespace firestarter::x86::payload { -auto SSE2Payload::compilePayload(const environment::payload::PayloadSettings& Settings, bool DumpRegisters, +auto SSE2Payload::compilePayload(const firestarter::payload::PayloadSettings& Settings, bool DumpRegisters, bool ErrorDetection, bool PrintAssembler) const - -> environment::payload::CompiledPayload::UniquePtr { + -> firestarter::payload::CompiledPayload::UniquePtr { using Imm = asmjit::Imm; using Mm = asmjit::x86::Mm; using Xmm = asmjit::x86::Xmm; @@ -37,10 +37,10 @@ auto SSE2Payload::compilePayload(const environment::payload::PayloadSettings& Se // to reach the desired size auto Sequence = Settings.sequence(); auto Repetitions = - environment::payload::PayloadSettings::getNumberOfSequenceRepetitions(Sequence, Settings.linesPerThread()); + firestarter::payload::PayloadSettings::getNumberOfSequenceRepetitions(Sequence, Settings.linesPerThread()); // compute count of flops and memory access for performance report - environment::payload::PayloadStats Stats; + firestarter::payload::PayloadStats Stats; for (const auto& Item : Sequence) { auto It = instructionFlops().find(Item); @@ -75,11 +75,11 @@ auto SSE2Payload::compilePayload(const environment::payload::PayloadSettings& Se // calculate the reset counters for the buffers const auto L2LoopCount = - environment::payload::PayloadSettings::getL2LoopCount(Sequence, Settings.linesPerThread(), L2Size); + firestarter::payload::PayloadSettings::getL2LoopCount(Sequence, Settings.linesPerThread(), L2Size); const auto L3LoopCount = - environment::payload::PayloadSettings::getL3LoopCount(Sequence, Settings.linesPerThread(), L3Size); + firestarter::payload::PayloadSettings::getL3LoopCount(Sequence, Settings.linesPerThread(), L3Size); const auto RamLoopCount = - environment::payload::PayloadSettings::getRAMLoopCount(Sequence, Settings.linesPerThread(), RamSize); + firestarter::payload::PayloadSettings::getRAMLoopCount(Sequence, Settings.linesPerThread(), RamSize); asmjit::CodeHolder Code; Code.init(asmjit::Environment::host()); @@ -325,7 +325,7 @@ auto SSE2Payload::compilePayload(const environment::payload::PayloadSettings& Se } } - if (environment::payload::PayloadSettings::getRAMSequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getRAMSequenceCount(Sequence) > 0) { // reset RAM counter auto NoRamReset = Cb.newLabel(); @@ -338,7 +338,7 @@ auto SSE2Payload::compilePayload(const environment::payload::PayloadSettings& Se // adds always two instruction Stats.Instructions += 2; } - if (environment::payload::PayloadSettings::getL2SequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getL2SequenceCount(Sequence) > 0) { // reset L2-Cache counter auto NoL2Reset = Cb.newLabel(); @@ -351,7 +351,7 @@ auto SSE2Payload::compilePayload(const environment::payload::PayloadSettings& Se // adds always two instruction Stats.Instructions += 2; } - if (environment::payload::PayloadSettings::getL3SequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getL3SequenceCount(Sequence) > 0) { // reset L3-Cache counter auto NoL3Reset = Cb.newLabel(); @@ -414,4 +414,4 @@ void SSE2Payload::init(double* MemoryAddr, uint64_t BufferSize) const { X86Payload::initMemory(MemoryAddr, BufferSize, 1.654738925401e-10, 1.654738925401e-15); } -} // namespace firestarter::environment::x86::payload \ No newline at end of file +} // namespace firestarter::x86::payload \ No newline at end of file diff --git a/src/firestarter/Environment/X86/Payload/X86Payload.cpp b/src/firestarter/X86/Payload/X86Payload.cpp similarity index 95% rename from src/firestarter/Environment/X86/Payload/X86Payload.cpp rename to src/firestarter/X86/Payload/X86Payload.cpp index 296d1052..a70b423e 100644 --- a/src/firestarter/Environment/X86/Payload/X86Payload.cpp +++ b/src/firestarter/X86/Payload/X86Payload.cpp @@ -19,7 +19,7 @@ * Contact: daniel.hackenberg@tu-dresden.de *****************************************************************************/ -#include "firestarter/Environment/X86/Payload/X86Payload.hpp" +#include "firestarter/X86/Payload/X86Payload.hpp" #include "firestarter/Constants.hpp" #include "firestarter/WindowsCompat.hpp" @@ -27,7 +27,7 @@ #include #include -namespace firestarter::environment::x86::payload { +namespace firestarter::x86::payload { void X86Payload::lowLoadFunction(volatile LoadThreadWorkType& LoadVar, std::chrono::microseconds Period) const { auto Nap = Period / 100; @@ -91,4 +91,4 @@ auto X86Payload::getAvailableInstructions() const -> std::list { return Instructions; } -}; // namespace firestarter::environment::x86::payload \ No newline at end of file +}; // namespace firestarter::x86::payload \ No newline at end of file diff --git a/src/firestarter/Environment/X86/Payload/ZENFMAPayload.cpp b/src/firestarter/X86/Payload/ZENFMAPayload.cpp similarity index 93% rename from src/firestarter/Environment/X86/Payload/ZENFMAPayload.cpp rename to src/firestarter/X86/Payload/ZENFMAPayload.cpp index f12dca1d..93e2b4a8 100644 --- a/src/firestarter/Environment/X86/Payload/ZENFMAPayload.cpp +++ b/src/firestarter/X86/Payload/ZENFMAPayload.cpp @@ -19,14 +19,14 @@ * Contact: daniel.hackenberg@tu-dresden.de *****************************************************************************/ -#include "firestarter/Environment/X86/Payload/ZENFMAPayload.hpp" -#include "firestarter/Environment/X86/Payload/CompiledX86Payload.hpp" +#include "firestarter/X86/Payload/ZENFMAPayload.hpp" +#include "firestarter/X86/Payload/CompiledX86Payload.hpp" -namespace firestarter::environment::x86::payload { +namespace firestarter::x86::payload { -auto ZENFMAPayload::compilePayload(const environment::payload::PayloadSettings& Settings, bool DumpRegisters, +auto ZENFMAPayload::compilePayload(const firestarter::payload::PayloadSettings& Settings, bool DumpRegisters, bool ErrorDetection, bool PrintAssembler) const - -> environment::payload::CompiledPayload::UniquePtr { + -> firestarter::payload::CompiledPayload::UniquePtr { using Imm = asmjit::Imm; using Xmm = asmjit::x86::Xmm; using Ymm = asmjit::x86::Ymm; @@ -37,10 +37,10 @@ auto ZENFMAPayload::compilePayload(const environment::payload::PayloadSettings& // to reach the desired size auto Sequence = Settings.sequence(); auto Repetitions = - environment::payload::PayloadSettings::getNumberOfSequenceRepetitions(Sequence, Settings.linesPerThread()); + firestarter::payload::PayloadSettings::getNumberOfSequenceRepetitions(Sequence, Settings.linesPerThread()); // compute count of flops and memory access for performance report - environment::payload::PayloadStats Stats; + firestarter::payload::PayloadStats Stats; for (const auto& Item : Sequence) { auto It = instructionFlops().find(Item); @@ -75,11 +75,11 @@ auto ZENFMAPayload::compilePayload(const environment::payload::PayloadSettings& // calculate the reset counters for the buffers const auto L2LoopCount = - environment::payload::PayloadSettings::getL2LoopCount(Sequence, Settings.linesPerThread(), L2Size); + firestarter::payload::PayloadSettings::getL2LoopCount(Sequence, Settings.linesPerThread(), L2Size); const auto L3LoopCount = - environment::payload::PayloadSettings::getL3LoopCount(Sequence, Settings.linesPerThread(), L3Size); + firestarter::payload::PayloadSettings::getL3LoopCount(Sequence, Settings.linesPerThread(), L3Size); const auto RamLoopCount = - environment::payload::PayloadSettings::getRAMLoopCount(Sequence, Settings.linesPerThread(), RamSize); + firestarter::payload::PayloadSettings::getRAMLoopCount(Sequence, Settings.linesPerThread(), RamSize); asmjit::CodeHolder Code; Code.init(asmjit::Environment::host()); @@ -291,7 +291,7 @@ auto ZENFMAPayload::compilePayload(const environment::payload::PayloadSettings& } Cb.movq(TempReg, IterReg); // restore iteration counter - if (environment::payload::PayloadSettings::getRAMSequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getRAMSequenceCount(Sequence) > 0) { // reset RAM counter auto NoRamReset = Cb.newLabel(); @@ -305,7 +305,7 @@ auto ZENFMAPayload::compilePayload(const environment::payload::PayloadSettings& Stats.Instructions += 2; } Cb.inc(TempReg); // increment iteration counter - if (environment::payload::PayloadSettings::getL2SequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getL2SequenceCount(Sequence) > 0) { // reset L2-Cache counter auto NoL2Reset = Cb.newLabel(); @@ -319,7 +319,7 @@ auto ZENFMAPayload::compilePayload(const environment::payload::PayloadSettings& Stats.Instructions += 2; } Cb.movq(IterReg, TempReg); // store iteration counter - if (environment::payload::PayloadSettings::getL3SequenceCount(Sequence) > 0) { + if (firestarter::payload::PayloadSettings::getL3SequenceCount(Sequence) > 0) { // reset L3-Cache counter auto NoL3Reset = Cb.newLabel(); @@ -381,4 +381,4 @@ void ZENFMAPayload::init(double* MemoryAddr, uint64_t BufferSize) const { X86Payload::initMemory(MemoryAddr, BufferSize, 0.27948995982e-4, 0.27948995982e-4); } -} // namespace firestarter::environment::x86::payload \ No newline at end of file +} // namespace firestarter::x86::payload \ No newline at end of file diff --git a/src/firestarter/Environment/X86/Platform/X86PlatformConfig.cpp b/src/firestarter/X86/Platform/X86PlatformConfig.cpp similarity index 95% rename from src/firestarter/Environment/X86/Platform/X86PlatformConfig.cpp rename to src/firestarter/X86/Platform/X86PlatformConfig.cpp index fa4d4399..cddd3af8 100644 --- a/src/firestarter/Environment/X86/Platform/X86PlatformConfig.cpp +++ b/src/firestarter/X86/Platform/X86PlatformConfig.cpp @@ -24,4 +24,4 @@ // included header. Therefore we should not see any errors in this file for missing includes. For more infomation // look in the LLVM code base: clang/lib/Tooling/InterpolatingCompilationDatabase.cpp -#include "firestarter/Environment/X86/Platform/X86PlatformConfig.hpp" \ No newline at end of file +#include "firestarter/X86/Platform/X86PlatformConfig.hpp" \ No newline at end of file diff --git a/src/firestarter/Environment/X86/X86ProcessorInformation.cpp b/src/firestarter/X86/X86ProcessorInformation.cpp similarity index 97% rename from src/firestarter/Environment/X86/X86ProcessorInformation.cpp rename to src/firestarter/X86/X86ProcessorInformation.cpp index 466c25db..5cdd57d2 100644 --- a/src/firestarter/Environment/X86/X86ProcessorInformation.cpp +++ b/src/firestarter/X86/X86ProcessorInformation.cpp @@ -19,7 +19,7 @@ * Contact: daniel.hackenberg@tu-dresden.de *****************************************************************************/ -#include "firestarter/Environment/X86/X86ProcessorInformation.hpp" +#include "firestarter/X86/X86ProcessorInformation.hpp" #include "firestarter/Logging/Log.hpp" #include @@ -31,7 +31,7 @@ #pragma intrinsic(__rdtsc) #endif -namespace firestarter::environment::x86 { +namespace firestarter::x86 { X86ProcessorInformation::X86ProcessorInformation() : ProcessorInformation("x86_64") @@ -254,4 +254,4 @@ void X86ProcessorInformation::cpuid(uint64_t* Rax, uint64_t* Rbx, uint64_t* Rcx, #endif } -} // namespace firestarter::environment::x86 \ No newline at end of file +} // namespace firestarter::x86 \ No newline at end of file diff --git a/test/DumpPayloads/Main.cpp b/test/DumpPayloads/Main.cpp index 7f7986f3..5dd086de 100644 --- a/test/DumpPayloads/Main.cpp +++ b/test/DumpPayloads/Main.cpp @@ -19,21 +19,21 @@ * Contact: daniel.hackenberg@tu-dresden.de *****************************************************************************/ -#include "firestarter/Environment/Payload/Payload.hpp" -#include "firestarter/Environment/X86/Payload/AVX512Payload.hpp" -#include "firestarter/Environment/X86/Payload/AVXPayload.hpp" -#include "firestarter/Environment/X86/Payload/FMA4Payload.hpp" -#include "firestarter/Environment/X86/Payload/FMAPayload.hpp" -#include "firestarter/Environment/X86/Payload/SSE2Payload.hpp" -#include "firestarter/Environment/X86/Payload/ZENFMAPayload.hpp" +#include "firestarter/Payload/Payload.hpp" +#include "firestarter/X86/Payload/AVX512Payload.hpp" +#include "firestarter/X86/Payload/AVXPayload.hpp" +#include "firestarter/X86/Payload/FMA4Payload.hpp" +#include "firestarter/X86/Payload/FMAPayload.hpp" +#include "firestarter/X86/Payload/SSE2Payload.hpp" +#include "firestarter/X86/Payload/ZENFMAPayload.hpp" namespace { /// Take a list of instructions and return a list with a pair containing the each instruction in the first element of /// the pair and a one in the second. auto oneEach(const std::list& Instructions) - -> std::vector { - std::vector OneEach; + -> std::vector { + std::vector OneEach; for (const auto& Instruction : Instructions) { OneEach.emplace_back(Instruction, 1); } @@ -41,14 +41,14 @@ auto oneEach(const std::list& Instructions) } /// Dump the generated assembler code of the payload with some given settings. Each item is printed once. -void dumpPayload(firestarter::environment::payload::Payload& PayloadPtr) { +void dumpPayload(firestarter::payload::Payload& PayloadPtr) { const auto& Instuctions = PayloadPtr.getAvailableInstructions(); - firestarter::environment::payload::PayloadSettings Settings(/*Threads=*/{1}, - /*DataCacheBufferSize=*/{32768, 1048576, 1441792}, - /*RamBufferSize=*/1048576000, - /*Lines=*/3 * Instuctions.size(), - /*InstructionGroups=*/oneEach(Instuctions)); + firestarter::payload::PayloadSettings Settings(/*Threads=*/{1}, + /*DataCacheBufferSize=*/{32768, 1048576, 1441792}, + /*RamBufferSize=*/1048576000, + /*Lines=*/3 * Instuctions.size(), + /*InstructionGroups=*/oneEach(Instuctions)); (void)PayloadPtr.compilePayload(Settings, /*DumpRegisters=*/false, /*ErrorDetection=*/false, /*PrintAssembler=*/true); @@ -57,13 +57,13 @@ void dumpPayload(firestarter::environment::payload::Payload& PayloadPtr) { } // namespace auto main(int /*argc*/, const char** /*argv*/) -> int { - const std::vector> PayloadPtrs = { - std::make_unique(), - std::make_unique(), - std::make_unique(), - std::make_unique(), - std::make_unique(), - std::make_unique()}; + const std::vector> PayloadPtrs = { + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique()}; for (const auto& PayloadPtr : PayloadPtrs) { firestarter::log::info() << "Payload " << PayloadPtr->name(); diff --git a/test/X86Functions/Main.cpp b/test/X86Functions/Main.cpp index 4b35389a..1e96e29f 100644 --- a/test/X86Functions/Main.cpp +++ b/test/X86Functions/Main.cpp @@ -19,12 +19,12 @@ * Contact: daniel.hackenberg@tu-dresden.de *****************************************************************************/ -#include "firestarter/Environment/X86/X86Environment.hpp" +#include "firestarter/X86/X86Environment.hpp" auto main(int /*argc*/, const char** /*argv*/) -> int { firestarter::logging::Filter::set_severity(nitro::log::severity_level::info); - firestarter::environment::x86::X86Environment Env; + firestarter::x86::X86Environment Env; Env.printFunctionSummary(/*ForceYes=*/true); From 5d1bc4ee4d8fae551e63145ac2c5ad1d40a0a3f8 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Tue, 10 Dec 2024 14:26:15 +0100 Subject: [PATCH 05/31] add refactor commit to .git-blame-ignore-revs --- .git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index d1806bac..81be32c1 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1 +1,2 @@ 9732bdb59717274f666e9c1497289d1f9a0d7858 +57259a1c5dce3b90a71520abc068af8aab37bb56 From 635460a649aad432ba7ff267f82b8f5a9a12830b Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Tue, 10 Dec 2024 14:57:13 +0100 Subject: [PATCH 06/31] cleanup Environment class --- .../Platform/PlatformConfigAndThreads.hpp | 68 +++++++++++++++++ src/firestarter/Environment.cpp | 76 ++++++++++--------- 2 files changed, 107 insertions(+), 37 deletions(-) create mode 100644 include/firestarter/Platform/PlatformConfigAndThreads.hpp diff --git a/include/firestarter/Platform/PlatformConfigAndThreads.hpp b/include/firestarter/Platform/PlatformConfigAndThreads.hpp new file mode 100644 index 00000000..8a9bc179 --- /dev/null +++ b/include/firestarter/Platform/PlatformConfigAndThreads.hpp @@ -0,0 +1,68 @@ +/****************************************************************************** + * FIRESTARTER - A Processor Stress Test Utility + * Copyright (C) 2024 TU Dresden, Center for Information Services and High + * Performance Computing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Contact: daniel.hackenberg@tu-dresden.de + *****************************************************************************/ + +#pragma once + +#include "firestarter/Platform/PlatformConfig.hpp" + +namespace firestarter::platform { + +/// This struct is used to iterate over the possible thread configurations available on each platform. +struct PlatformConfigAndThreads { +public: + PlatformConfigAndThreads() = delete; + + /// The shared pointer to the platform config + std::shared_ptr Config; + /// One concreate thread count which is available in the given config + unsigned ThreadCount; + + /// Get the vector of available configurations for a specific platform config. + /// \arg Config The reference to the platform config + /// \returns The vector of available configurations for this platform config. + [[nodiscard]] static auto fromPlatformConfig(const std::shared_ptr& Config) + -> std::vector { + std::vector Vec; + + for (const auto& Thread : Config->settings().threads()) { + Vec.emplace_back(PlatformConfigAndThreads{Config, Thread}); + } + + return Vec; + } + + /// Get the vector of available configurations for a vector of platform configs. + /// \arg Configs The reference to the vector of platform config + /// \returns The vector of available configurations for the supplied platform config. + [[nodiscard]] static auto fromPlatformConfigs(const std::vector>& Configs) + -> std::vector { + std::vector Vec; + + for (const auto& Config : Configs) { + const auto ConfigAndThreads = fromPlatformConfig(Config); + Vec.insert(Vec.end(), ConfigAndThreads.cbegin(), ConfigAndThreads.cend()); + } + + return Vec; + } +}; + +} // namespace firestarter::platform diff --git a/src/firestarter/Environment.cpp b/src/firestarter/Environment.cpp index 380fa138..51cfe741 100644 --- a/src/firestarter/Environment.cpp +++ b/src/firestarter/Environment.cpp @@ -21,6 +21,7 @@ #include "firestarter/Environment.hpp" #include "firestarter/Logging/Log.hpp" +#include "firestarter/Platform/PlatformConfigAndThreads.hpp" #include #include @@ -36,36 +37,34 @@ void Environment::selectFunction(std::optional FunctionId, const CPUTo const auto ProcessorICacheSize = Topology.instructionCacheSize(); const auto ProcessorThreadsPerCore = Topology.homogenousResourceCount().NumThreadsPerCore; - for (const auto& PlatformConfigPtr : platformConfigs()) { - for (auto const& ThreadsPerCore : PlatformConfigPtr->settings().threads()) { - if (FunctionId) { - // the selected function - if (Id == *FunctionId) { - if (!PlatformConfigPtr->isAvailable(processorInfos())) { - const auto ErrorString = - "Function " + std::to_string(*FunctionId) + " (\"" + PlatformConfigPtr->functionName(ThreadsPerCore) + - "\") requires " + PlatformConfigPtr->payload()->name() + ", which is not supported by the processor."; - if (AllowUnavailablePayload) { - log::warn() << ErrorString; - } else { - throw std::invalid_argument(ErrorString); - } + for (const auto& Platform : platform::PlatformConfigAndThreads::fromPlatformConfigs(platformConfigs())) { + if (FunctionId) { + // the selected function + if (Id == *FunctionId) { + if (!Platform.Config->isAvailable(processorInfos())) { + const auto ErrorString = "Function " + std::to_string(*FunctionId) + " (\"" + + Platform.Config->functionName(Platform.ThreadCount) + "\") requires " + + Platform.Config->payload()->name() + ", which is not supported by the processor."; + if (AllowUnavailablePayload) { + log::warn() << ErrorString; + } else { + throw std::invalid_argument(ErrorString); } - // found function - setConfig(PlatformConfigPtr->cloneConcreate(ProcessorICacheSize, ThreadsPerCore)); - return; } - } else { - // default function - if (PlatformConfigPtr->isDefault(processorInfos())) { - if (ThreadsPerCore == ProcessorThreadsPerCore) { - setConfig(PlatformConfigPtr->cloneConcreate(ProcessorICacheSize, ThreadsPerCore)); - return; - } - DefaultPayloadName = PlatformConfigPtr->payload()->name(); + // found function + setConfig(Platform.Config->cloneConcreate(ProcessorICacheSize, Platform.ThreadCount)); + return; + } + } else { + // default function + if (Platform.Config->isDefault(processorInfos())) { + if (Platform.ThreadCount == ProcessorThreadsPerCore) { + setConfig(Platform.Config->cloneConcreate(ProcessorICacheSize, Platform.ThreadCount)); + return; } - Id++; + DefaultPayloadName = Platform.Config->payload()->name(); } + Id++; } } @@ -89,19 +88,22 @@ void Environment::selectFunction(std::optional FunctionId, const CPUTo // fallback for (const auto& FallbackPlatformConfigPtr : fallbackPlatformConfigs()) { if (FallbackPlatformConfigPtr->isAvailable(processorInfos())) { - std::optional SelectedThreadsPerCore; - // find the fallback implementation with the correct thread per core count - for (auto const& ThreadsPerCore : FallbackPlatformConfigPtr->settings().threads()) { - if (ThreadsPerCore == ProcessorThreadsPerCore) { - SelectedThreadsPerCore = ThreadsPerCore; + unsigned SelectedThreadsPerCore{}; + + // find the fallback implementation with the correct thread per core count or select the first available thread + // per core count + { + const auto& Threads = FallbackPlatformConfigPtr->settings().threads(); + const auto& ThreadIt = std::find(Threads.cbegin(), Threads.cend(), ProcessorThreadsPerCore); + if (ThreadIt == Threads.cend()) { + SelectedThreadsPerCore = Threads.front(); + } else { + SelectedThreadsPerCore = *ThreadIt; } } - // Otherwise select the first available thread per core count - if (!SelectedThreadsPerCore) { - SelectedThreadsPerCore = FallbackPlatformConfigPtr->settings().threads().front(); - } - setConfig(FallbackPlatformConfigPtr->cloneConcreate(ProcessorICacheSize, *SelectedThreadsPerCore)); - log::warn() << "Using function " << FallbackPlatformConfigPtr->functionName(*SelectedThreadsPerCore) + + setConfig(FallbackPlatformConfigPtr->cloneConcreate(ProcessorICacheSize, SelectedThreadsPerCore)); + log::warn() << "Using function " << FallbackPlatformConfigPtr->functionName(SelectedThreadsPerCore) << " as fallback.\n" << "You can use the parameter --function to try other " "functions."; From a4754a490c2d1bce801d31fcb0cb894979be7563 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Tue, 10 Dec 2024 15:05:26 +0100 Subject: [PATCH 07/31] split function selection code --- include/firestarter/Environment.hpp | 11 +++++ src/firestarter/Environment.cpp | 72 ++++++++++++++++------------- 2 files changed, 52 insertions(+), 31 deletions(-) diff --git a/include/firestarter/Environment.hpp b/include/firestarter/Environment.hpp index 18bec434..df519b05 100644 --- a/include/firestarter/Environment.hpp +++ b/include/firestarter/Environment.hpp @@ -49,6 +49,17 @@ class Environment { /// \arg AllowUnavailablePayload If true we will not throw if the PlatformConfig is not available. void selectFunction(std::optional FunctionId, const CPUTopology& Topology, bool AllowUnavailablePayload); + /// Select a PlatformConfig based on its generated id. This function will throw if a payload is not available or the + /// id is incorrect. + /// \arg FunctionId The id of the PlatformConfig that should be selected. + /// \arg Topology The topology which contains information about the cpu requied to select the correct function. + /// \arg AllowUnavailablePayload If true we will not throw if the PlatformConfig is not available. + void selectAvailableFunction(unsigned FunctionId, const CPUTopology& Topology, bool AllowUnavailablePayload); + + /// Select the fallback PlatformConfig if no id is given. + /// \arg Topology The topology which contains information about the cpu requied to select the correct function. + void selectDefaultOrFallbackFunction(const CPUTopology& Topology); + /// Parse the selected payload instruction groups and save the in the selected function. Throws if the input is /// invalid. /// \arg Groups The list of instruction groups that is in the format: multiple INSTRUCTION:VALUE pairs diff --git a/src/firestarter/Environment.cpp b/src/firestarter/Environment.cpp index 51cfe741..b6d947c8 100644 --- a/src/firestarter/Environment.cpp +++ b/src/firestarter/Environment.cpp @@ -30,47 +30,48 @@ namespace firestarter { -void Environment::selectFunction(std::optional FunctionId, const CPUTopology& Topology, - bool AllowUnavailablePayload) { +void Environment::selectAvailableFunction(unsigned FunctionId, const CPUTopology& Topology, + bool AllowUnavailablePayload) { unsigned Id = 1; std::optional DefaultPayloadName; const auto ProcessorICacheSize = Topology.instructionCacheSize(); - const auto ProcessorThreadsPerCore = Topology.homogenousResourceCount().NumThreadsPerCore; for (const auto& Platform : platform::PlatformConfigAndThreads::fromPlatformConfigs(platformConfigs())) { - if (FunctionId) { - // the selected function - if (Id == *FunctionId) { - if (!Platform.Config->isAvailable(processorInfos())) { - const auto ErrorString = "Function " + std::to_string(*FunctionId) + " (\"" + - Platform.Config->functionName(Platform.ThreadCount) + "\") requires " + - Platform.Config->payload()->name() + ", which is not supported by the processor."; - if (AllowUnavailablePayload) { - log::warn() << ErrorString; - } else { - throw std::invalid_argument(ErrorString); - } - } - // found function - setConfig(Platform.Config->cloneConcreate(ProcessorICacheSize, Platform.ThreadCount)); - return; - } - } else { - // default function - if (Platform.Config->isDefault(processorInfos())) { - if (Platform.ThreadCount == ProcessorThreadsPerCore) { - setConfig(Platform.Config->cloneConcreate(ProcessorICacheSize, Platform.ThreadCount)); - return; + // the selected function + if (Id == FunctionId) { + if (!Platform.Config->isAvailable(processorInfos())) { + const auto ErrorString = "Function " + std::to_string(FunctionId) + " (\"" + + Platform.Config->functionName(Platform.ThreadCount) + "\") requires " + + Platform.Config->payload()->name() + ", which is not supported by the processor."; + if (AllowUnavailablePayload) { + log::warn() << ErrorString; + } else { + throw std::invalid_argument(ErrorString); } - DefaultPayloadName = Platform.Config->payload()->name(); } - Id++; + // found function + setConfig(Platform.Config->cloneConcreate(ProcessorICacheSize, Platform.ThreadCount)); + return; } } - if (FunctionId) { - throw std::invalid_argument("unknown function id: " + std::to_string(*FunctionId) + - ", see --avail for available ids"); + throw std::invalid_argument("unknown function id: " + std::to_string(FunctionId) + ", see --avail for available ids"); +} + +void Environment::selectDefaultOrFallbackFunction(const CPUTopology& Topology) { + std::optional DefaultPayloadName; + const auto ProcessorICacheSize = Topology.instructionCacheSize(); + const auto ProcessorThreadsPerCore = Topology.homogenousResourceCount().NumThreadsPerCore; + + for (const auto& Platform : platform::PlatformConfigAndThreads::fromPlatformConfigs(platformConfigs())) { + // default function + if (Platform.Config->isDefault(processorInfos())) { + if (Platform.ThreadCount == ProcessorThreadsPerCore) { + setConfig(Platform.Config->cloneConcreate(ProcessorICacheSize, Platform.ThreadCount)); + return; + } + DefaultPayloadName = Platform.Config->payload()->name(); + } } // no default found @@ -116,6 +117,15 @@ void Environment::selectFunction(std::optional FunctionId, const CPUTo "extensions."); } +void Environment::selectFunction(std::optional FunctionId, const CPUTopology& Topology, + bool AllowUnavailablePayload) { + if (FunctionId) { + selectAvailableFunction(*FunctionId, Topology, AllowUnavailablePayload); + } else { + selectDefaultOrFallbackFunction(Topology); + } +} + void Environment::selectInstructionGroups(const std::string& Groups) { const auto Delimiter = ','; const std::regex Re("^(\\w+):(\\d+)$"); From 57fed06535e58f5ec8df6fb82968e475362195a4 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Tue, 10 Dec 2024 15:12:24 +0100 Subject: [PATCH 08/31] move code to payload class --- include/firestarter/Payload/Payload.hpp | 18 ++++++++++++++++++ src/firestarter/Environment.cpp | 14 ++------------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/include/firestarter/Payload/Payload.hpp b/include/firestarter/Payload/Payload.hpp index 8a465808..1cd64103 100644 --- a/include/firestarter/Payload/Payload.hpp +++ b/include/firestarter/Payload/Payload.hpp @@ -102,6 +102,24 @@ class Payload { /// Get the available instruction items that are supported by this payload. /// \returns The available instruction items that are supported by this payload. [[nodiscard]] virtual auto getAvailableInstructions() const -> std::list = 0; + + /// Print the available instruction groups of this payload + /// \arg Stream The stream to which the message will be saved. + void printAvailableInstructionGroups(std::ostream& Stream) const { + std::stringstream Ss; + + for (auto const& Item : getAvailableInstructions()) { + Ss << Item << ","; + } + + auto S = Ss.str(); + if (!S.empty()) { + S.pop_back(); + } + + Stream << " available instruction-groups for payload " << name() << ":\n" + << " " << S; + } }; } // namespace firestarter::payload diff --git a/src/firestarter/Environment.cpp b/src/firestarter/Environment.cpp index b6d947c8..35af78d0 100644 --- a/src/firestarter/Environment.cpp +++ b/src/firestarter/Environment.cpp @@ -167,18 +167,8 @@ void Environment::selectInstructionGroups(const std::string& Groups) { void Environment::printAvailableInstructionGroups() { std::stringstream Ss; - - for (auto const& Item : config().payload()->getAvailableInstructions()) { - Ss << Item << ","; - } - - auto S = Ss.str(); - if (!S.empty()) { - S.pop_back(); - } - - log::info() << " available instruction-groups for payload " << config().payload()->name() << ":\n" - << " " << S; + config().payload()->printAvailableInstructionGroups(Ss); + log::info() << Ss.str(); } void Environment::setLineCount(unsigned LineCount) { config().settings().setLineCount(LineCount); } From d64961b857f681525fdee3874bfd7fb26d502703 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Tue, 10 Dec 2024 16:09:22 +0100 Subject: [PATCH 09/31] refactor function selection --- include/firestarter/Environment.hpp | 119 ------------------ include/firestarter/Firestarter.hpp | 7 +- include/firestarter/FunctionSelection.hpp | 80 ++++++++++++ include/firestarter/LoadWorkerData.hpp | 19 +-- .../firestarter/Platform/PlatformConfig.hpp | 49 +++++++- ...vironment.hpp => X86FunctionSelection.hpp} | 32 +---- .../X86/X86ProcessorInformation.hpp | 6 - src/CMakeLists.txt | 2 +- src/firestarter/Firestarter.cpp | 31 +++-- ...{Environment.cpp => FunctionSelection.cpp} | 109 +++++----------- src/firestarter/LoadWorker.cpp | 16 +-- test/X86Functions/Main.cpp | 9 +- 12 files changed, 212 insertions(+), 267 deletions(-) delete mode 100644 include/firestarter/Environment.hpp create mode 100644 include/firestarter/FunctionSelection.hpp rename include/firestarter/X86/{X86Environment.hpp => X86FunctionSelection.hpp} (73%) rename src/firestarter/{Environment.cpp => FunctionSelection.cpp} (54%) diff --git a/include/firestarter/Environment.hpp b/include/firestarter/Environment.hpp deleted file mode 100644 index df519b05..00000000 --- a/include/firestarter/Environment.hpp +++ /dev/null @@ -1,119 +0,0 @@ -/****************************************************************************** - * FIRESTARTER - A Processor Stress Test Utility - * Copyright (C) 2020 TU Dresden, Center for Information Services and High - * Performance Computing - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Contact: daniel.hackenberg@tu-dresden.de - *****************************************************************************/ - -#pragma once - -#include "firestarter/CPUTopology.hpp" -#include "firestarter/Platform/PlatformConfig.hpp" -#include "firestarter/ProcessorInformation.hpp" - -#include -#include - -namespace firestarter { - -/// This class handles parsing of user input to FIRESTARTER, namely the number of threads used, the thread affinity, the -/// selection of the correct high-load function, selection of the instruction groups and number of lines. It also -/// handles printing useful information, provides interfaces to the PlatformConfig and the number of threads. It -/// facilitates setting the cpu affinity in further parts of FIRESTARTER. -class Environment { -public: - Environment() = delete; - explicit Environment(std::unique_ptr&& Topology) - : ProcessorInfos(std::move(Topology)) {} - virtual ~Environment() = default; - - /// Select a PlatformConfig based on its generated id. This function will throw if a payload is not available or the - /// id is incorrect. - /// \arg FunctionId The id of the PlatformConfig that should be selected or automatically select a matching - /// PlatformConfig. - /// \arg Topology The topology which contains information about the cpu requied to select the correct function. - /// \arg AllowUnavailablePayload If true we will not throw if the PlatformConfig is not available. - void selectFunction(std::optional FunctionId, const CPUTopology& Topology, bool AllowUnavailablePayload); - - /// Select a PlatformConfig based on its generated id. This function will throw if a payload is not available or the - /// id is incorrect. - /// \arg FunctionId The id of the PlatformConfig that should be selected. - /// \arg Topology The topology which contains information about the cpu requied to select the correct function. - /// \arg AllowUnavailablePayload If true we will not throw if the PlatformConfig is not available. - void selectAvailableFunction(unsigned FunctionId, const CPUTopology& Topology, bool AllowUnavailablePayload); - - /// Select the fallback PlatformConfig if no id is given. - /// \arg Topology The topology which contains information about the cpu requied to select the correct function. - void selectDefaultOrFallbackFunction(const CPUTopology& Topology); - - /// Parse the selected payload instruction groups and save the in the selected function. Throws if the input is - /// invalid. - /// \arg Groups The list of instruction groups that is in the format: multiple INSTRUCTION:VALUE pairs - /// comma-seperated. - void selectInstructionGroups(const std::string& Groups); - - /// Print the available instruction groups of the selected function. - void printAvailableInstructionGroups(); - - /// Set the line count in the selected function. - /// \arg LineCount The maximum number of instruction that should be in the high-load loop. - void setLineCount(unsigned LineCount); - - /// Print a summary of the settings of the selected config. - void printSelectedCodePathSummary(); - - /// Print a list of available high-load function and if they are available on the current system. - /// \arg ForceYes Force all functions to be shown as avaialable - void printFunctionSummary(bool ForceYes) const; - - /// Getter (which allows modifying) for the current platform config containing the payload, settings and the - /// associated name. - [[nodiscard]] virtual auto config() -> platform::PlatformConfig& { - assert(Config && "No PlatformConfig selected"); - return *Config; - } - - /// Const getter for the current platform config containing the payload, settings and the associated name. - [[nodiscard]] virtual auto config() const -> const platform::PlatformConfig& { - assert(Config && "No PlatformConfig selected"); - return *Config; - } - - /// Const getter for the current processor information. - [[nodiscard]] virtual auto processorInfos() const -> const ProcessorInformation& { - assert(ProcessorInfos && "ProcessorInfos is a nullptr"); - return *ProcessorInfos; - } - - [[nodiscard]] virtual auto platformConfigs() const - -> const std::vector>& = 0; - - [[nodiscard]] virtual auto fallbackPlatformConfigs() const - -> const std::vector>& = 0; - -protected: - /// This function sets the config based on the - void setConfig(std::unique_ptr&& Config) { this->Config = std::move(Config); } - -private: - /// The selected config that contains the payload, settings and the associated name. - std::unique_ptr Config; - /// The description of the current CPU. - std::unique_ptr ProcessorInfos; -}; - -} // namespace firestarter diff --git a/include/firestarter/Firestarter.hpp b/include/firestarter/Firestarter.hpp index a90fa3cb..7d09843c 100644 --- a/include/firestarter/Firestarter.hpp +++ b/include/firestarter/Firestarter.hpp @@ -31,6 +31,7 @@ #include "firestarter/Optimizer/Algorithm.hpp" #include "firestarter/Optimizer/OptimizerWorker.hpp" #include "firestarter/Optimizer/Population.hpp" +#include "firestarter/ProcessorInformation.hpp" #include "firestarter/ThreadAffinity.hpp" #include @@ -68,8 +69,12 @@ class Firestarter { /// This class handles getting the topology information of the processor and is used to set thread binding. std::unique_ptr Topology; + /// This class holds the information about the current processor which is specific to one architecture. + std::shared_ptr ProcessorInfos; /// The class that handles setting up the payload for firestarter - std::unique_ptr EnvironmentPtr; + std::unique_ptr FunctionSelectionPtr; + /// The selection function. + std::unique_ptr FunctionPtr; /// The class for execution of the gemm routine on Cuda or HIP GPUs. std::unique_ptr Cuda; /// The class for execution of the gemm routine on OneAPI GPUs. diff --git a/include/firestarter/FunctionSelection.hpp b/include/firestarter/FunctionSelection.hpp new file mode 100644 index 00000000..3df6ed38 --- /dev/null +++ b/include/firestarter/FunctionSelection.hpp @@ -0,0 +1,80 @@ +/****************************************************************************** + * FIRESTARTER - A Processor Stress Test Utility + * Copyright (C) 2020 TU Dresden, Center for Information Services and High + * Performance Computing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Contact: daniel.hackenberg@tu-dresden.de + *****************************************************************************/ + +#pragma once + +#include "firestarter/CPUTopology.hpp" +#include "firestarter/Platform/PlatformConfig.hpp" +#include "firestarter/ProcessorInformation.hpp" + +#include +#include + +namespace firestarter { + +class FunctionSelection { +public: + FunctionSelection() = default; + virtual ~FunctionSelection() = default; + + /// Select a PlatformConfig based on its generated id. This function will throw if a payload is not available or the + /// id is incorrect. + /// \arg FunctionId The id of the PlatformConfig that should be selected or automatically select a matching + /// PlatformConfig. + /// \arg ProcessorInfos Information about the processor which is specific to the current ISA. + /// \arg Topology The topology which contains information about the cpu requied to select the correct function. + /// \arg AllowUnavailablePayload If true we will not throw if the PlatformConfig is not available. + [[nodiscard]] auto selectFunction(std::optional FunctionId, + const std::shared_ptr& ProcessorInfos, + const CPUTopology& Topology, bool AllowUnavailablePayload) const + -> std::unique_ptr; + + /// Select a PlatformConfig based on its generated id. This function will throw if a payload is not available or the + /// id is incorrect. + /// \arg FunctionId The id of the PlatformConfig that should be selected. + /// \arg ProcessorInfos Information about the processor which is specific to the current ISA. + /// \arg Topology The topology which contains information about the cpu requied to select the correct function. + /// \arg AllowUnavailablePayload If true we will not throw if the PlatformConfig is not available. + [[nodiscard]] auto selectAvailableFunction(unsigned FunctionId, + const std::shared_ptr& ProcessorInfos, + const CPUTopology& Topology, bool AllowUnavailablePayload) const + -> std::unique_ptr; + + /// Select the fallback PlatformConfig if no id is given. + /// \arg ProcessorInfos Information about the processor which is specific to the current ISA. + /// \arg Topology The topology which contains information about the cpu requied to select the correct function. + [[nodiscard]] auto selectDefaultOrFallbackFunction(const std::shared_ptr& ProcessorInfos, + const CPUTopology& Topology) const + -> std::unique_ptr; + + /// Print a list of available high-load function and if they are available on the current system. + /// \arg ProcessorInfos Information about the processor which is specific to the current ISA. + /// \arg ForceYes Force all functions to be shown as avaialable + void printFunctionSummary(const std::shared_ptr& ProcessorInfos, bool ForceYes) const; + + [[nodiscard]] virtual auto platformConfigs() const + -> const std::vector>& = 0; + + [[nodiscard]] virtual auto fallbackPlatformConfigs() const + -> const std::vector>& = 0; +}; + +} // namespace firestarter diff --git a/include/firestarter/LoadWorkerData.hpp b/include/firestarter/LoadWorkerData.hpp index 649dded7..b5f1d7af 100644 --- a/include/firestarter/LoadWorkerData.hpp +++ b/include/firestarter/LoadWorkerData.hpp @@ -23,9 +23,10 @@ #include "firestarter/CPUTopology.hpp" #include "firestarter/Constants.hpp" -#include "firestarter/Environment.hpp" +#include "firestarter/FunctionSelection.hpp" #include "firestarter/LoadWorkerMemory.hpp" #include "firestarter/Platform/PlatformConfig.hpp" +#include "firestarter/ProcessorInformation.hpp" #include #include @@ -64,7 +65,8 @@ class LoadWorkerData { /// Create the datastructure that is shared between a load worker thread and firestarter. /// \arg Id The id of the load worker thread. They are counted from 0 to the maximum number of threads - 1. /// \arg OsIndex The os index to which this thread should be bound. - /// \arg Environment The reference to the environment which allows getting the current timestamp. + /// \arg ProcessorInfos The reference to the ProcessorInfos which allows getting the current timestamp. + /// \arg FunctionPtr The config that is cloned for this specific load worker. /// \arg Topology The reference to the processor topology abstraction which allows setting thread affinity. /// \arg LoadVar The variable that controls the execution of the load worker. /// \arg Period Is used in combination with the LoadVar for the low load routine. @@ -72,7 +74,8 @@ class LoadWorkerData { /// compiled payload. /// \arg ErrorDetection Should the code to support error detection between thread be baked into the high load routine /// of the compiled payload. - LoadWorkerData(uint64_t Id, uint64_t OsIndex, const Environment& EnvironmentRef, const CPUTopology& Topology, + LoadWorkerData(uint64_t Id, uint64_t OsIndex, const std::shared_ptr& ProcessorInfos, + const std::unique_ptr& FunctionPtr, const CPUTopology& Topology, volatile LoadThreadWorkType& LoadVar, std::chrono::microseconds Period, bool DumpRegisters, bool ErrorDetection) : LoadVar(LoadVar) @@ -81,9 +84,9 @@ class LoadWorkerData { , ErrorDetection(ErrorDetection) , Id(Id) , OsIndex(OsIndex) - , EnvironmentRef(EnvironmentRef) + , ProcessorInfos(ProcessorInfos) , Topology(Topology) - , Config(EnvironmentRef.config().clone()) {} + , Config(FunctionPtr->clone()) {} ~LoadWorkerData() = default; @@ -99,8 +102,6 @@ class LoadWorkerData { /// Gettter for the id of the thread. [[nodiscard]] auto id() const -> uint64_t { return Id; } - /// Const getter for the environment. - [[nodiscard]] auto environment() const -> const Environment& { return EnvironmentRef; } /// Getter for the current platform config. [[nodiscard]] auto config() const -> platform::PlatformConfig& { return *Config; } @@ -166,10 +167,10 @@ class LoadWorkerData { /// The os index to which this thread should be bound. const uint64_t OsIndex; /// The reference to the environment which allows getting the current timestamp. - const Environment& EnvironmentRef; + std::shared_ptr ProcessorInfos; /// The reference to the processor topology abstraction which allows setting thread affinity. const CPUTopology& Topology; - /// The config that is cloned from the environment for this specfic load worker. + /// The config that is cloned for this specific load worker. std::unique_ptr Config; }; diff --git a/include/firestarter/Platform/PlatformConfig.hpp b/include/firestarter/Platform/PlatformConfig.hpp index e9a49058..c853b0c7 100644 --- a/include/firestarter/Platform/PlatformConfig.hpp +++ b/include/firestarter/Platform/PlatformConfig.hpp @@ -21,9 +21,13 @@ #pragma once +#include "firestarter/Logging/Log.hpp" #include "firestarter/Payload/Payload.hpp" #include "firestarter/ProcessorInformation.hpp" -#include "firestarter/Logging/Log.hpp" + +#include +#include +#include namespace firestarter::platform { @@ -99,6 +103,49 @@ class PlatformConfig { [[nodiscard]] virtual auto cloneConcreate(std::optional InstructionCacheSize, unsigned ThreadsPerCore) const -> std::unique_ptr = 0; + /// Parse the selected payload instruction groups and save the in the selected function. Throws if the input is + /// invalid. + /// \arg Groups The list of instruction groups that is in the format: multiple INSTRUCTION:VALUE pairs + /// comma-seperated. + void selectInstructionGroups(const std::string& Groups) { + const auto Delimiter = ','; + const std::regex Re("^(\\w+):(\\d+)$"); + const auto AvailableInstructionGroups = payload()->getAvailableInstructions(); + + std::stringstream Ss(Groups); + std::vector> PayloadSettings = {}; + + while (Ss.good()) { + std::string Token; + std::smatch M; + std::getline(Ss, Token, Delimiter); + + if (std::regex_match(Token, M, Re)) { + if (std::find(AvailableInstructionGroups.begin(), AvailableInstructionGroups.end(), M[1].str()) == + AvailableInstructionGroups.end()) { + throw std::invalid_argument("Invalid instruction-group: " + M[1].str() + + "\n --run-instruction-groups format: multiple INST:VAL " + "pairs comma-seperated"); + } + auto Num = std::stoul(M[2].str()); + if (Num == 0) { + throw std::invalid_argument("instruction-group VAL may not contain number 0" + "\n --run-instruction-groups format: multiple INST:VAL " + "pairs comma-seperated"); + } + PayloadSettings.emplace_back(M[1].str(), Num); + } else { + throw std::invalid_argument("Invalid symbols in instruction-group: " + Token + + "\n --run-instruction-groups format: multiple INST:VAL " + "pairs comma-seperated"); + } + } + + settings().selectInstructionGroups(PayloadSettings); + + log::info() << " Running custom instruction group: " << Groups; + } + /// The function name for this platform config given a specific thread per core count. /// \arg ThreadsPerCore The number of threads per core. /// \returns The name of the function (a platform name, payload name and a specific thread per core count) diff --git a/include/firestarter/X86/X86Environment.hpp b/include/firestarter/X86/X86FunctionSelection.hpp similarity index 73% rename from include/firestarter/X86/X86Environment.hpp rename to include/firestarter/X86/X86FunctionSelection.hpp index a9e948fa..7d591c66 100644 --- a/include/firestarter/X86/X86Environment.hpp +++ b/include/firestarter/X86/X86FunctionSelection.hpp @@ -21,7 +21,7 @@ #pragma once -#include "firestarter/Environment.hpp" +#include "firestarter/FunctionSelection.hpp" #include "firestarter/X86/Platform/BulldozerConfig.hpp" #include "firestarter/X86/Platform/HaswellConfig.hpp" #include "firestarter/X86/Platform/HaswellEPConfig.hpp" @@ -34,37 +34,13 @@ #include "firestarter/X86/Platform/SandyBridgeEPConfig.hpp" #include "firestarter/X86/Platform/SkylakeConfig.hpp" #include "firestarter/X86/Platform/SkylakeSPConfig.hpp" -#include "firestarter/X86/Platform/X86PlatformConfig.hpp" +#include namespace firestarter::x86 { -class X86Environment final : public Environment { +class X86FunctionSelection final : public FunctionSelection { public: - X86Environment() - : Environment(std::make_unique()) {} - - /// Getter (which allows modifying) for the current platform config containing the payload, settings, the - /// associated name and the default X86 family and models. - [[nodiscard]] auto config() -> platform::X86PlatformConfig& final { - auto* X86PlatformConfig = dynamic_cast(&Environment::config()); - assert(X86PlatformConfig && "X86PlatformConfig is a nullptr"); - return *X86PlatformConfig; - } - - /// Const getter for the current platform config containing the payload, settings, the associated name and the default - /// X86 family and models. - [[nodiscard]] auto config() const -> const platform::X86PlatformConfig& final { - const auto* X86PlatformConfig = dynamic_cast(&Environment::config()); - assert(X86PlatformConfig && "X86PlatformConfig is a nullptr"); - return *X86PlatformConfig; - } - - /// Const getter for the current processor information with X86 specific modifications. - [[nodiscard]] auto processorInfos() const -> const X86ProcessorInformation& final { - const auto* X86Topology = dynamic_cast(&Environment::processorInfos()); - assert(X86Topology && "X86Topology is a nullptr"); - return *X86Topology; - } + X86FunctionSelection() = default; [[nodiscard]] auto platformConfigs() const -> const std::vector>& override { diff --git a/include/firestarter/X86/X86ProcessorInformation.hpp b/include/firestarter/X86/X86ProcessorInformation.hpp index 3acda6da..b7922a66 100644 --- a/include/firestarter/X86/X86ProcessorInformation.hpp +++ b/include/firestarter/X86/X86ProcessorInformation.hpp @@ -32,8 +32,6 @@ class X86ProcessorInformation final : public ProcessorInformation { public: X86ProcessorInformation(); - friend auto operator<<(std::ostream& Stream, X86ProcessorInformation const& CpuTopology) -> std::ostream&; - /// Getter for the list of CPU features [[nodiscard]] auto features() const -> std::list const& override { return this->FeatureList; } /// Getter for the CPU features class from asmjit @@ -81,8 +79,4 @@ class X86ProcessorInformation final : public ProcessorInformation { std::string Model; }; -inline auto operator<<(std::ostream& Stream, X86ProcessorInformation const& CpuTopology) -> std::ostream& { - return CpuTopology.print(Stream); -} - } // namespace firestarter::x86 \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c8b07886..fbe99350 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,7 +6,7 @@ add_library(firestartercore STATIC firestarter/DumpRegisterWorker.cpp firestarter/CPUTopology.cpp firestarter/ThreadAffinity.cpp - firestarter/Environment.cpp + firestarter/FunctionSelection.cpp firestarter/ProcessorInformation.cpp firestarter/Config/Config.cpp diff --git a/src/firestarter/Firestarter.cpp b/src/firestarter/Firestarter.cpp index 1b42870d..cdbf26ae 100644 --- a/src/firestarter/Firestarter.cpp +++ b/src/firestarter/Firestarter.cpp @@ -25,7 +25,7 @@ #include "firestarter/Optimizer/Algorithm/NSGA2.hpp" #include "firestarter/Optimizer/History.hpp" #include "firestarter/Optimizer/Problem/CLIArgumentProblem.hpp" -#include "firestarter/X86/X86Environment.hpp" +#include "firestarter/X86/X86FunctionSelection.hpp" #include #include @@ -37,7 +37,8 @@ Firestarter::Firestarter(Config&& ProvidedConfig) : Cfg(std::move(ProvidedConfig)) , Topology(std::make_unique()) { if constexpr (firestarter::OptionalFeatures.IsX86) { - EnvironmentPtr = std::make_unique(); + ProcessorInfos = std::make_shared(); + FunctionSelectionPtr = std::make_unique(); } const auto Affinity = @@ -46,8 +47,8 @@ Firestarter::Firestarter(Config&& ProvidedConfig) if constexpr (firestarter::OptionalFeatures.IsX86) { // Error detection uses crc32 instruction added by the SSE4.2 extension to x86 if (Cfg.ErrorDetection) { - const auto& X86Env = *dynamic_cast(EnvironmentPtr.get()); - if (!X86Env.processorInfos().featuresAsmjit().has(asmjit::CpuFeatures::X86::kSSE4_2)) { + const auto& X86ProcessorInfos = *dynamic_cast(ProcessorInfos.get()); + if (!X86ProcessorInfos.featuresAsmjit().has(asmjit::CpuFeatures::X86::kSSE4_2)) { throw std::invalid_argument("Option --error-detection requires the crc32 " "instruction added with SSE_4_2.\n"); } @@ -61,23 +62,27 @@ Firestarter::Firestarter(Config&& ProvidedConfig) } if (Cfg.PrintFunctionSummary) { - EnvironmentPtr->printFunctionSummary(/*ForceYes=*/false); + FunctionSelectionPtr->printFunctionSummary(ProcessorInfos, /*ForceYes=*/false); safeExit(EXIT_SUCCESS); } - EnvironmentPtr->selectFunction(Cfg.FunctionId, *Topology, Cfg.AllowUnavailablePayload); + FunctionPtr = + FunctionSelectionPtr->selectFunction(Cfg.FunctionId, ProcessorInfos, *Topology, Cfg.AllowUnavailablePayload); if (Cfg.ListInstructionGroups) { - EnvironmentPtr->printAvailableInstructionGroups(); + std::stringstream Ss; + FunctionPtr->payload()->printAvailableInstructionGroups(Ss); + log::info() << Ss.str(); + safeExit(EXIT_SUCCESS); } if (!Cfg.InstructionGroups.empty()) { - EnvironmentPtr->selectInstructionGroups(Cfg.InstructionGroups); + FunctionPtr->selectInstructionGroups(Cfg.InstructionGroups); } if (Cfg.LineCount != 0) { - EnvironmentPtr->setLineCount(Cfg.LineCount); + FunctionPtr->settings().setLineCount(Cfg.LineCount); } if constexpr (firestarter::OptionalFeatures.OptimizationEnabled) { @@ -152,7 +157,7 @@ Firestarter::Firestarter(Config&& ProvidedConfig) auto Prob = std::make_shared( std::move(ApplySettings), MeasurementWorker, Cfg.OptimizationMetrics, Cfg.EvaluationDuration, Cfg.StartDelta, - Cfg.StopDelta, EnvironmentPtr->config().settings().instructionGroupItems()); + Cfg.StopDelta, FunctionPtr->settings().instructionGroupItems()); Population = std::make_unique(std::move(Prob)); @@ -167,14 +172,14 @@ Firestarter::Firestarter(Config&& ProvidedConfig) } } - EnvironmentPtr->printSelectedCodePathSummary(); + FunctionPtr->printCodePathSummary(); { std::stringstream Ss; Topology->printSystemSummary(Ss); Ss << "\n"; - Ss << EnvironmentPtr->processorInfos(); + Ss << ProcessorInfos; Topology->printCacheSummary(Ss); log::info() << Ss.str(); @@ -229,7 +234,7 @@ void Firestarter::mainThread() { Firestarter::Optimizer->join(); Firestarter::Optimizer.reset(); - auto PayloadItems = EnvironmentPtr->config().settings().instructionGroupItems(); + auto PayloadItems = FunctionPtr->settings().instructionGroupItems(); firestarter::optimizer::History::save(Cfg.OptimizeOutfile, StartTime, PayloadItems, Cfg.Argc, Cfg.Argv); diff --git a/src/firestarter/Environment.cpp b/src/firestarter/FunctionSelection.cpp similarity index 54% rename from src/firestarter/Environment.cpp rename to src/firestarter/FunctionSelection.cpp index 35af78d0..aa960300 100644 --- a/src/firestarter/Environment.cpp +++ b/src/firestarter/FunctionSelection.cpp @@ -19,19 +19,20 @@ * Contact: daniel.hackenberg@tu-dresden.de *****************************************************************************/ -#include "firestarter/Environment.hpp" +#include "firestarter/FunctionSelection.hpp" #include "firestarter/Logging/Log.hpp" #include "firestarter/Platform/PlatformConfigAndThreads.hpp" #include #include #include -#include namespace firestarter { -void Environment::selectAvailableFunction(unsigned FunctionId, const CPUTopology& Topology, - bool AllowUnavailablePayload) { +auto FunctionSelection::selectAvailableFunction(unsigned FunctionId, + const std::shared_ptr& ProcessorInfos, + const CPUTopology& Topology, bool AllowUnavailablePayload) const + -> std::unique_ptr { unsigned Id = 1; std::optional DefaultPayloadName; const auto ProcessorICacheSize = Topology.instructionCacheSize(); @@ -39,7 +40,7 @@ void Environment::selectAvailableFunction(unsigned FunctionId, const CPUTopology for (const auto& Platform : platform::PlatformConfigAndThreads::fromPlatformConfigs(platformConfigs())) { // the selected function if (Id == FunctionId) { - if (!Platform.Config->isAvailable(processorInfos())) { + if (!Platform.Config->isAvailable(*ProcessorInfos)) { const auto ErrorString = "Function " + std::to_string(FunctionId) + " (\"" + Platform.Config->functionName(Platform.ThreadCount) + "\") requires " + Platform.Config->payload()->name() + ", which is not supported by the processor."; @@ -50,25 +51,25 @@ void Environment::selectAvailableFunction(unsigned FunctionId, const CPUTopology } } // found function - setConfig(Platform.Config->cloneConcreate(ProcessorICacheSize, Platform.ThreadCount)); - return; + return Platform.Config->cloneConcreate(ProcessorICacheSize, Platform.ThreadCount); } } throw std::invalid_argument("unknown function id: " + std::to_string(FunctionId) + ", see --avail for available ids"); } -void Environment::selectDefaultOrFallbackFunction(const CPUTopology& Topology) { +auto FunctionSelection::selectDefaultOrFallbackFunction(const std::shared_ptr& ProcessorInfos, + const CPUTopology& Topology) const + -> std::unique_ptr { std::optional DefaultPayloadName; const auto ProcessorICacheSize = Topology.instructionCacheSize(); const auto ProcessorThreadsPerCore = Topology.homogenousResourceCount().NumThreadsPerCore; for (const auto& Platform : platform::PlatformConfigAndThreads::fromPlatformConfigs(platformConfigs())) { // default function - if (Platform.Config->isDefault(processorInfos())) { + if (Platform.Config->isDefault(*ProcessorInfos)) { if (Platform.ThreadCount == ProcessorThreadsPerCore) { - setConfig(Platform.Config->cloneConcreate(ProcessorICacheSize, Platform.ThreadCount)); - return; + return Platform.Config->cloneConcreate(ProcessorICacheSize, Platform.ThreadCount); } DefaultPayloadName = Platform.Config->payload()->name(); } @@ -81,14 +82,14 @@ void Environment::selectDefaultOrFallbackFunction(const CPUTopology& Topology) { // supported log::warn() << "No " << *DefaultPayloadName << " code path for " << ProcessorThreadsPerCore << " threads per core!"; } - log::warn() << processorInfos().vendor() << " " << processorInfos().model() + log::warn() << ProcessorInfos->vendor() << " " << ProcessorInfos->model() << " is not supported by this version of FIRESTARTER!\n" << "Check project website for updates."; // loop over available implementation and check if they are marked as // fallback for (const auto& FallbackPlatformConfigPtr : fallbackPlatformConfigs()) { - if (FallbackPlatformConfigPtr->isAvailable(processorInfos())) { + if (FallbackPlatformConfigPtr->isAvailable(*ProcessorInfos)) { unsigned SelectedThreadsPerCore{}; // find the fallback implementation with the correct thread per core count or select the first available thread @@ -103,12 +104,11 @@ void Environment::selectDefaultOrFallbackFunction(const CPUTopology& Topology) { } } - setConfig(FallbackPlatformConfigPtr->cloneConcreate(ProcessorICacheSize, SelectedThreadsPerCore)); log::warn() << "Using function " << FallbackPlatformConfigPtr->functionName(SelectedThreadsPerCore) << " as fallback.\n" << "You can use the parameter --function to try other " "functions."; - return; + return FallbackPlatformConfigPtr->cloneConcreate(ProcessorICacheSize, SelectedThreadsPerCore); } } @@ -117,65 +117,18 @@ void Environment::selectDefaultOrFallbackFunction(const CPUTopology& Topology) { "extensions."); } -void Environment::selectFunction(std::optional FunctionId, const CPUTopology& Topology, - bool AllowUnavailablePayload) { +auto FunctionSelection::selectFunction(std::optional FunctionId, + const std::shared_ptr& ProcessorInfos, + const CPUTopology& Topology, bool AllowUnavailablePayload) const + -> std::unique_ptr { if (FunctionId) { - selectAvailableFunction(*FunctionId, Topology, AllowUnavailablePayload); - } else { - selectDefaultOrFallbackFunction(Topology); + return selectAvailableFunction(*FunctionId, ProcessorInfos, Topology, AllowUnavailablePayload); } + return selectDefaultOrFallbackFunction(ProcessorInfos, Topology); } -void Environment::selectInstructionGroups(const std::string& Groups) { - const auto Delimiter = ','; - const std::regex Re("^(\\w+):(\\d+)$"); - const auto AvailableInstructionGroups = config().payload()->getAvailableInstructions(); - - std::stringstream Ss(Groups); - std::vector> PayloadSettings = {}; - - while (Ss.good()) { - std::string Token; - std::smatch M; - std::getline(Ss, Token, Delimiter); - - if (std::regex_match(Token, M, Re)) { - if (std::find(AvailableInstructionGroups.begin(), AvailableInstructionGroups.end(), M[1].str()) == - AvailableInstructionGroups.end()) { - throw std::invalid_argument("Invalid instruction-group: " + M[1].str() + - "\n --run-instruction-groups format: multiple INST:VAL " - "pairs comma-seperated"); - } - auto Num = std::stoul(M[2].str()); - if (Num == 0) { - throw std::invalid_argument("instruction-group VAL may not contain number 0" - "\n --run-instruction-groups format: multiple INST:VAL " - "pairs comma-seperated"); - } - PayloadSettings.emplace_back(M[1].str(), Num); - } else { - throw std::invalid_argument("Invalid symbols in instruction-group: " + Token + - "\n --run-instruction-groups format: multiple INST:VAL " - "pairs comma-seperated"); - } - } - - config().settings().selectInstructionGroups(PayloadSettings); - - log::info() << " Running custom instruction group: " << Groups; -} - -void Environment::printAvailableInstructionGroups() { - std::stringstream Ss; - config().payload()->printAvailableInstructionGroups(Ss); - log::info() << Ss.str(); -} - -void Environment::setLineCount(unsigned LineCount) { config().settings().setLineCount(LineCount); } - -void Environment::printSelectedCodePathSummary() { config().printCodePathSummary(); } - -void Environment::printFunctionSummary(bool ForceYes) const { +void FunctionSelection::printFunctionSummary(const std::shared_ptr& ProcessorInfos, + bool ForceYes) const { log::info() << " available load-functions:\n" << " ID | NAME | available on this " "system | payload default setting\n" @@ -186,16 +139,14 @@ void Environment::printFunctionSummary(bool ForceYes) const { auto Id = 1U; - for (auto const& Config : platformConfigs()) { - for (auto const& ThreadsPerCore : Config->settings().threads()) { - const char* Available = (Config->isAvailable(processorInfos()) || ForceYes) ? "yes" : "no"; - const auto& FunctionName = Config->functionName(ThreadsPerCore); - const auto& InstructionGroupsString = Config->settings().getInstructionGroupsString(); + for (const auto& Platform : platform::PlatformConfigAndThreads::fromPlatformConfigs(platformConfigs())) { + const char* Available = (Platform.Config->isAvailable(*ProcessorInfos) || ForceYes) ? "yes" : "no"; + const auto& FunctionName = Platform.Config->functionName(Platform.ThreadCount); + const auto& InstructionGroupsString = Platform.Config->settings().getInstructionGroupsString(); - log::info() << " " << std::right << std::setw(4) << Id << " | " << std::left << std::setw(30) << FunctionName - << " | " << std::left << std::setw(24) << Available << " | " << InstructionGroupsString; - Id++; - } + log::info() << " " << std::right << std::setw(4) << Id << " | " << std::left << std::setw(30) << FunctionName + << " | " << std::left << std::setw(24) << Available << " | " << InstructionGroupsString; + Id++; } } diff --git a/src/firestarter/LoadWorker.cpp b/src/firestarter/LoadWorker.cpp index e1cc2342..d1c25dc3 100644 --- a/src/firestarter/LoadWorker.cpp +++ b/src/firestarter/LoadWorker.cpp @@ -20,6 +20,7 @@ *****************************************************************************/ #include "firestarter/AlignedAlloc.hpp" +#include "firestarter/Config/Config.hpp" #include "firestarter/Constants.hpp" #include "firestarter/ErrorDetectionStruct.hpp" #include "firestarter/Firestarter.hpp" @@ -71,8 +72,9 @@ void Firestarter::initLoadWorkers(const ThreadAffinity& Affinity) { } for (uint64_t I = 0; I < Affinity.RequestedNumThreads; I++) { - auto Td = std::make_shared(I, Affinity.CpuBind[I], std::cref(*EnvironmentPtr), std::cref(*Topology), - std::ref(LoadVar), Cfg.Period, Cfg.DumpRegisters, Cfg.ErrorDetection); + auto Td = std::make_shared(I, Affinity.CpuBind[I], std::cref(ProcessorInfos), + std::cref(FunctionPtr), std::cref(*Topology), std::ref(LoadVar), + Cfg.Period, Cfg.DumpRegisters, Cfg.ErrorDetection); if (Cfg.ErrorDetection) { // distribute pointers for error deteciton. (set threads in a ring) @@ -192,8 +194,8 @@ void Firestarter::printPerformanceReport() { Iterations += Td->LastRun.Iterations.load(); } - double const Runtime = static_cast(StopTimestamp - StartTimestamp) / - static_cast(EnvironmentPtr->processorInfos().clockrate()); + double const Runtime = + static_cast(StopTimestamp - StartTimestamp) / static_cast(ProcessorInfos->clockrate()); double const GFlops = static_cast(LoadThreads.front().second->CompiledPayloadPtr->stats().Flops) * 0.000000001 * static_cast(Iterations) / Runtime; double const Bandwidth = static_cast(LoadThreads.front().second->CompiledPayloadPtr->stats().Bytes) * @@ -304,7 +306,7 @@ void Firestarter::loadThreadWorker(const std::shared_ptr& Td) { case LoadThreadState::ThreadWork: Td->CurrentRun.Iterations = 0; // record threads start timestamp - Td->CurrentRun.StartTsc = Td->environment().processorInfos().timestamp(); + Td->CurrentRun.StartTsc = Td->ProcessorInfos->timestamp(); // will be terminated by watchdog for (;;) { @@ -337,14 +339,14 @@ void Firestarter::loadThreadWorker(const std::shared_ptr& Td) { // terminate if master signals end of run and record stop timestamp if (Td->LoadVar == LoadThreadWorkType::LoadStop) { - Td->CurrentRun.StopTsc = Td->environment().processorInfos().timestamp(); + Td->CurrentRun.StopTsc = Td->ProcessorInfos->timestamp(); Td->LastRun = Td->CurrentRun; return; } if (Td->LoadVar == LoadThreadWorkType::LoadSwitch) { - Td->CurrentRun.StopTsc = Td->environment().processorInfos().timestamp(); + Td->CurrentRun.StopTsc = Td->ProcessorInfos->timestamp(); Td->LastRun = Td->CurrentRun; break; diff --git a/test/X86Functions/Main.cpp b/test/X86Functions/Main.cpp index 1e96e29f..d817231e 100644 --- a/test/X86Functions/Main.cpp +++ b/test/X86Functions/Main.cpp @@ -19,14 +19,17 @@ * Contact: daniel.hackenberg@tu-dresden.de *****************************************************************************/ -#include "firestarter/X86/X86Environment.hpp" +#include "firestarter/X86/X86FunctionSelection.hpp" +#include "firestarter/X86/X86ProcessorInformation.hpp" +#include auto main(int /*argc*/, const char** /*argv*/) -> int { firestarter::logging::Filter::set_severity(nitro::log::severity_level::info); - firestarter::x86::X86Environment Env; + firestarter::x86::X86FunctionSelection Env; + const auto ProcessorInfos = std::make_shared(); - Env.printFunctionSummary(/*ForceYes=*/true); + Env.printFunctionSummary(ProcessorInfos, /*ForceYes=*/true); return EXIT_SUCCESS; } \ No newline at end of file From 27129cc0d9e2f884d6b8f4dd9a24546bb073ca10 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Tue, 10 Dec 2024 16:10:55 +0100 Subject: [PATCH 10/31] fix function selection --- src/firestarter/FunctionSelection.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/firestarter/FunctionSelection.cpp b/src/firestarter/FunctionSelection.cpp index aa960300..6dabe64e 100644 --- a/src/firestarter/FunctionSelection.cpp +++ b/src/firestarter/FunctionSelection.cpp @@ -53,6 +53,7 @@ auto FunctionSelection::selectAvailableFunction(unsigned FunctionId, // found function return Platform.Config->cloneConcreate(ProcessorICacheSize, Platform.ThreadCount); } + Id++; } throw std::invalid_argument("unknown function id: " + std::to_string(FunctionId) + ", see --avail for available ids"); From ce627b8588b747174ae16cfe13bafb3e57a7f7d9 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Tue, 10 Dec 2024 16:35:59 +0100 Subject: [PATCH 11/31] cleanup --- include/firestarter/FunctionSelection.hpp | 10 ++++----- include/firestarter/ProcessorInformation.hpp | 6 +++--- .../X86/X86ProcessorInformation.hpp | 6 ++++++ src/firestarter/Firestarter.cpp | 6 +++--- src/firestarter/FunctionSelection.cpp | 21 ++++++++----------- test/X86Functions/Main.cpp | 3 +-- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/include/firestarter/FunctionSelection.hpp b/include/firestarter/FunctionSelection.hpp index 3df6ed38..eacc1003 100644 --- a/include/firestarter/FunctionSelection.hpp +++ b/include/firestarter/FunctionSelection.hpp @@ -42,8 +42,7 @@ class FunctionSelection { /// \arg ProcessorInfos Information about the processor which is specific to the current ISA. /// \arg Topology The topology which contains information about the cpu requied to select the correct function. /// \arg AllowUnavailablePayload If true we will not throw if the PlatformConfig is not available. - [[nodiscard]] auto selectFunction(std::optional FunctionId, - const std::shared_ptr& ProcessorInfos, + [[nodiscard]] auto selectFunction(std::optional FunctionId, const ProcessorInformation& ProcessorInfos, const CPUTopology& Topology, bool AllowUnavailablePayload) const -> std::unique_ptr; @@ -53,22 +52,21 @@ class FunctionSelection { /// \arg ProcessorInfos Information about the processor which is specific to the current ISA. /// \arg Topology The topology which contains information about the cpu requied to select the correct function. /// \arg AllowUnavailablePayload If true we will not throw if the PlatformConfig is not available. - [[nodiscard]] auto selectAvailableFunction(unsigned FunctionId, - const std::shared_ptr& ProcessorInfos, + [[nodiscard]] auto selectAvailableFunction(unsigned FunctionId, const ProcessorInformation& ProcessorInfos, const CPUTopology& Topology, bool AllowUnavailablePayload) const -> std::unique_ptr; /// Select the fallback PlatformConfig if no id is given. /// \arg ProcessorInfos Information about the processor which is specific to the current ISA. /// \arg Topology The topology which contains information about the cpu requied to select the correct function. - [[nodiscard]] auto selectDefaultOrFallbackFunction(const std::shared_ptr& ProcessorInfos, + [[nodiscard]] auto selectDefaultOrFallbackFunction(const ProcessorInformation& ProcessorInfos, const CPUTopology& Topology) const -> std::unique_ptr; /// Print a list of available high-load function and if they are available on the current system. /// \arg ProcessorInfos Information about the processor which is specific to the current ISA. /// \arg ForceYes Force all functions to be shown as avaialable - void printFunctionSummary(const std::shared_ptr& ProcessorInfos, bool ForceYes) const; + void printFunctionSummary(const ProcessorInformation& ProcessorInfos, bool ForceYes) const; [[nodiscard]] virtual auto platformConfigs() const -> const std::vector>& = 0; diff --git a/include/firestarter/ProcessorInformation.hpp b/include/firestarter/ProcessorInformation.hpp index e8d8cefe..1cd4c437 100644 --- a/include/firestarter/ProcessorInformation.hpp +++ b/include/firestarter/ProcessorInformation.hpp @@ -39,7 +39,7 @@ class ProcessorInformation { explicit ProcessorInformation(std::string Architecture); virtual ~ProcessorInformation() = default; - friend auto operator<<(std::ostream& Stream, ProcessorInformation const& CpuTopologyRef) -> std::ostream&; + friend auto operator<<(std::ostream& Stream, ProcessorInformation const& ProcessorInfos) -> std::ostream&; /// Getter for the clockrate in Hz [[nodiscard]] virtual auto clockrate() const -> uint64_t { return Clockrate; } @@ -84,8 +84,8 @@ class ProcessorInformation { uint64_t Clockrate = 0; }; -inline auto operator<<(std::ostream& Stream, ProcessorInformation const& CpuTopologyRef) -> std::ostream& { - return CpuTopologyRef.print(Stream); +inline auto operator<<(std::ostream& Stream, ProcessorInformation const& ProcessorInfos) -> std::ostream& { + return ProcessorInfos.print(Stream); } } // namespace firestarter diff --git a/include/firestarter/X86/X86ProcessorInformation.hpp b/include/firestarter/X86/X86ProcessorInformation.hpp index b7922a66..553c56e8 100644 --- a/include/firestarter/X86/X86ProcessorInformation.hpp +++ b/include/firestarter/X86/X86ProcessorInformation.hpp @@ -32,6 +32,8 @@ class X86ProcessorInformation final : public ProcessorInformation { public: X86ProcessorInformation(); + friend auto operator<<(std::ostream& Stream, X86ProcessorInformation const& ProcessorInfos) -> std::ostream&; + /// Getter for the list of CPU features [[nodiscard]] auto features() const -> std::list const& override { return this->FeatureList; } /// Getter for the CPU features class from asmjit @@ -79,4 +81,8 @@ class X86ProcessorInformation final : public ProcessorInformation { std::string Model; }; +inline auto operator<<(std::ostream& Stream, X86ProcessorInformation const& ProcessorInfos) -> std::ostream& { + return ProcessorInfos.print(Stream); +} + } // namespace firestarter::x86 \ No newline at end of file diff --git a/src/firestarter/Firestarter.cpp b/src/firestarter/Firestarter.cpp index cdbf26ae..ec08ccd5 100644 --- a/src/firestarter/Firestarter.cpp +++ b/src/firestarter/Firestarter.cpp @@ -62,12 +62,12 @@ Firestarter::Firestarter(Config&& ProvidedConfig) } if (Cfg.PrintFunctionSummary) { - FunctionSelectionPtr->printFunctionSummary(ProcessorInfos, /*ForceYes=*/false); + FunctionSelectionPtr->printFunctionSummary(*ProcessorInfos, /*ForceYes=*/false); safeExit(EXIT_SUCCESS); } FunctionPtr = - FunctionSelectionPtr->selectFunction(Cfg.FunctionId, ProcessorInfos, *Topology, Cfg.AllowUnavailablePayload); + FunctionSelectionPtr->selectFunction(Cfg.FunctionId, *ProcessorInfos, *Topology, Cfg.AllowUnavailablePayload); if (Cfg.ListInstructionGroups) { std::stringstream Ss; @@ -179,7 +179,7 @@ Firestarter::Firestarter(Config&& ProvidedConfig) Topology->printSystemSummary(Ss); Ss << "\n"; - Ss << ProcessorInfos; + Ss << *ProcessorInfos; Topology->printCacheSummary(Ss); log::info() << Ss.str(); diff --git a/src/firestarter/FunctionSelection.cpp b/src/firestarter/FunctionSelection.cpp index 6dabe64e..57bedc5d 100644 --- a/src/firestarter/FunctionSelection.cpp +++ b/src/firestarter/FunctionSelection.cpp @@ -29,8 +29,7 @@ namespace firestarter { -auto FunctionSelection::selectAvailableFunction(unsigned FunctionId, - const std::shared_ptr& ProcessorInfos, +auto FunctionSelection::selectAvailableFunction(unsigned FunctionId, const ProcessorInformation& ProcessorInfos, const CPUTopology& Topology, bool AllowUnavailablePayload) const -> std::unique_ptr { unsigned Id = 1; @@ -40,7 +39,7 @@ auto FunctionSelection::selectAvailableFunction(unsigned FunctionId, for (const auto& Platform : platform::PlatformConfigAndThreads::fromPlatformConfigs(platformConfigs())) { // the selected function if (Id == FunctionId) { - if (!Platform.Config->isAvailable(*ProcessorInfos)) { + if (!Platform.Config->isAvailable(ProcessorInfos)) { const auto ErrorString = "Function " + std::to_string(FunctionId) + " (\"" + Platform.Config->functionName(Platform.ThreadCount) + "\") requires " + Platform.Config->payload()->name() + ", which is not supported by the processor."; @@ -59,7 +58,7 @@ auto FunctionSelection::selectAvailableFunction(unsigned FunctionId, throw std::invalid_argument("unknown function id: " + std::to_string(FunctionId) + ", see --avail for available ids"); } -auto FunctionSelection::selectDefaultOrFallbackFunction(const std::shared_ptr& ProcessorInfos, +auto FunctionSelection::selectDefaultOrFallbackFunction(const ProcessorInformation& ProcessorInfos, const CPUTopology& Topology) const -> std::unique_ptr { std::optional DefaultPayloadName; @@ -68,7 +67,7 @@ auto FunctionSelection::selectDefaultOrFallbackFunction(const std::shared_ptrisDefault(*ProcessorInfos)) { + if (Platform.Config->isDefault(ProcessorInfos)) { if (Platform.ThreadCount == ProcessorThreadsPerCore) { return Platform.Config->cloneConcreate(ProcessorICacheSize, Platform.ThreadCount); } @@ -83,14 +82,14 @@ auto FunctionSelection::selectDefaultOrFallbackFunction(const std::shared_ptrvendor() << " " << ProcessorInfos->model() + log::warn() << ProcessorInfos.vendor() << " " << ProcessorInfos.model() << " is not supported by this version of FIRESTARTER!\n" << "Check project website for updates."; // loop over available implementation and check if they are marked as // fallback for (const auto& FallbackPlatformConfigPtr : fallbackPlatformConfigs()) { - if (FallbackPlatformConfigPtr->isAvailable(*ProcessorInfos)) { + if (FallbackPlatformConfigPtr->isAvailable(ProcessorInfos)) { unsigned SelectedThreadsPerCore{}; // find the fallback implementation with the correct thread per core count or select the first available thread @@ -118,8 +117,7 @@ auto FunctionSelection::selectDefaultOrFallbackFunction(const std::shared_ptr FunctionId, - const std::shared_ptr& ProcessorInfos, +auto FunctionSelection::selectFunction(std::optional FunctionId, const ProcessorInformation& ProcessorInfos, const CPUTopology& Topology, bool AllowUnavailablePayload) const -> std::unique_ptr { if (FunctionId) { @@ -128,8 +126,7 @@ auto FunctionSelection::selectFunction(std::optional FunctionId, return selectDefaultOrFallbackFunction(ProcessorInfos, Topology); } -void FunctionSelection::printFunctionSummary(const std::shared_ptr& ProcessorInfos, - bool ForceYes) const { +void FunctionSelection::printFunctionSummary(const ProcessorInformation& ProcessorInfos, bool ForceYes) const { log::info() << " available load-functions:\n" << " ID | NAME | available on this " "system | payload default setting\n" @@ -141,7 +138,7 @@ void FunctionSelection::printFunctionSummary(const std::shared_ptrisAvailable(*ProcessorInfos) || ForceYes) ? "yes" : "no"; + const char* Available = (Platform.Config->isAvailable(ProcessorInfos) || ForceYes) ? "yes" : "no"; const auto& FunctionName = Platform.Config->functionName(Platform.ThreadCount); const auto& InstructionGroupsString = Platform.Config->settings().getInstructionGroupsString(); diff --git a/test/X86Functions/Main.cpp b/test/X86Functions/Main.cpp index d817231e..37579348 100644 --- a/test/X86Functions/Main.cpp +++ b/test/X86Functions/Main.cpp @@ -21,13 +21,12 @@ #include "firestarter/X86/X86FunctionSelection.hpp" #include "firestarter/X86/X86ProcessorInformation.hpp" -#include auto main(int /*argc*/, const char** /*argv*/) -> int { firestarter::logging::Filter::set_severity(nitro::log::severity_level::info); firestarter::x86::X86FunctionSelection Env; - const auto ProcessorInfos = std::make_shared(); + const firestarter::x86::X86ProcessorInformation ProcessorInfos{}; Env.printFunctionSummary(ProcessorInfos, /*ForceYes=*/true); From 2929c42ddd4e0d0fb9ccf4768f0a9765be266949 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Tue, 10 Dec 2024 16:38:16 +0100 Subject: [PATCH 12/31] remove one smart pointer --- include/firestarter/Firestarter.hpp | 3 ++- src/firestarter/Firestarter.cpp | 13 ++++++------- src/firestarter/LoadWorker.cpp | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/firestarter/Firestarter.hpp b/include/firestarter/Firestarter.hpp index 7d09843c..4be5b1a6 100644 --- a/include/firestarter/Firestarter.hpp +++ b/include/firestarter/Firestarter.hpp @@ -21,6 +21,7 @@ #pragma once +#include "firestarter/CPUTopology.hpp" #include "firestarter/Config/Config.hpp" #include "firestarter/Constants.hpp" #include "firestarter/Cuda/Cuda.hpp" @@ -68,7 +69,7 @@ class Firestarter { const Config Cfg; /// This class handles getting the topology information of the processor and is used to set thread binding. - std::unique_ptr Topology; + CPUTopology Topology; /// This class holds the information about the current processor which is specific to one architecture. std::shared_ptr ProcessorInfos; /// The class that handles setting up the payload for firestarter diff --git a/src/firestarter/Firestarter.cpp b/src/firestarter/Firestarter.cpp index ec08ccd5..f945399b 100644 --- a/src/firestarter/Firestarter.cpp +++ b/src/firestarter/Firestarter.cpp @@ -34,15 +34,14 @@ namespace firestarter { Firestarter::Firestarter(Config&& ProvidedConfig) - : Cfg(std::move(ProvidedConfig)) - , Topology(std::make_unique()) { + : Cfg(std::move(ProvidedConfig)) { if constexpr (firestarter::OptionalFeatures.IsX86) { ProcessorInfos = std::make_shared(); FunctionSelectionPtr = std::make_unique(); } const auto Affinity = - ThreadAffinity::fromCommandLine(Topology->hardwareThreadsInfo(), Cfg.RequestedNumThreads, Cfg.CpuBinding); + ThreadAffinity::fromCommandLine(Topology.hardwareThreadsInfo(), Cfg.RequestedNumThreads, Cfg.CpuBinding); if constexpr (firestarter::OptionalFeatures.IsX86) { // Error detection uses crc32 instruction added by the SSE4.2 extension to x86 @@ -67,7 +66,7 @@ Firestarter::Firestarter(Config&& ProvidedConfig) } FunctionPtr = - FunctionSelectionPtr->selectFunction(Cfg.FunctionId, *ProcessorInfos, *Topology, Cfg.AllowUnavailablePayload); + FunctionSelectionPtr->selectFunction(Cfg.FunctionId, *ProcessorInfos, Topology, Cfg.AllowUnavailablePayload); if (Cfg.ListInstructionGroups) { std::stringstream Ss; @@ -177,15 +176,15 @@ Firestarter::Firestarter(Config&& ProvidedConfig) { std::stringstream Ss; - Topology->printSystemSummary(Ss); + Topology.printSystemSummary(Ss); Ss << "\n"; Ss << *ProcessorInfos; - Topology->printCacheSummary(Ss); + Topology.printCacheSummary(Ss); log::info() << Ss.str(); } - Affinity.printThreadSummary(*Topology); + Affinity.printThreadSummary(Topology); // setup thread with either high or low load configured at the start // low loads has to know the length of the period diff --git a/src/firestarter/LoadWorker.cpp b/src/firestarter/LoadWorker.cpp index d1c25dc3..9627629d 100644 --- a/src/firestarter/LoadWorker.cpp +++ b/src/firestarter/LoadWorker.cpp @@ -50,7 +50,7 @@ namespace firestarter { void Firestarter::initLoadWorkers(const ThreadAffinity& Affinity) { // Bind this thread to the first available CPU. - Topology->bindCallerToOsIndex(Affinity.CpuBind[0]); + Topology.bindCallerToOsIndex(Affinity.CpuBind[0]); // setup load variable to execute low or high load once the threads switch to // work. @@ -73,7 +73,7 @@ void Firestarter::initLoadWorkers(const ThreadAffinity& Affinity) { for (uint64_t I = 0; I < Affinity.RequestedNumThreads; I++) { auto Td = std::make_shared(I, Affinity.CpuBind[I], std::cref(ProcessorInfos), - std::cref(FunctionPtr), std::cref(*Topology), std::ref(LoadVar), + std::cref(FunctionPtr), std::cref(Topology), std::ref(LoadVar), Cfg.Period, Cfg.DumpRegisters, Cfg.ErrorDetection); if (Cfg.ErrorDetection) { From 62659a4f210143e0110cdab65217e31a71c2c398 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Wed, 11 Dec 2024 00:48:54 +0100 Subject: [PATCH 13/31] split instruction group parsing --- include/firestarter/CPUTopology.hpp | 4 +- include/firestarter/Config/Config.hpp | 8 ++- .../firestarter/Config/InstructionGroups.hpp | 62 +++++++++++++++++++ include/firestarter/Payload/Payload.hpp | 8 +-- .../firestarter/Platform/PlatformConfig.hpp | 39 +++--------- include/firestarter/ProcessorInformation.hpp | 12 +--- .../firestarter/X86/X86FunctionSelection.hpp | 1 + .../X86/X86ProcessorInformation.hpp | 6 -- src/CMakeLists.txt | 1 + src/firestarter/CPUTopology.cpp | 24 +++---- src/firestarter/Config/Config.cpp | 6 +- src/firestarter/Config/InstructionGroups.cpp | 58 +++++++++++++++++ src/firestarter/Firestarter.cpp | 27 +++----- src/firestarter/ProcessorInformation.cpp | 19 +++--- test/DumpCPUTopology/Main.cpp | 8 +-- 15 files changed, 180 insertions(+), 103 deletions(-) create mode 100644 include/firestarter/Config/InstructionGroups.hpp create mode 100644 src/firestarter/Config/InstructionGroups.cpp diff --git a/include/firestarter/CPUTopology.hpp b/include/firestarter/CPUTopology.hpp index d0371dfe..b129d96a 100644 --- a/include/firestarter/CPUTopology.hpp +++ b/include/firestarter/CPUTopology.hpp @@ -64,10 +64,10 @@ class CPUTopology { virtual ~CPUTopology(); /// Print information about the number of packages, cores and threads. - void printSystemSummary(std::ostream& Stream) const; + void printSystemSummary() const; /// Print information about the cache hierarchy. - void printCacheSummary(std::ostream& Stream) const; + void printCacheSummary() const; /// Get the size of the first instruction cache. [[nodiscard]] auto instructionCacheSize() const -> std::optional; diff --git a/include/firestarter/Config/Config.hpp b/include/firestarter/Config/Config.hpp index 17c64e8b..fdb47596 100644 --- a/include/firestarter/Config/Config.hpp +++ b/include/firestarter/Config/Config.hpp @@ -21,6 +21,8 @@ #pragma once +#include "firestarter/Config/InstructionGroups.hpp" + #include #include #include @@ -69,7 +71,7 @@ struct Config { /// The optional cpu bind that allow pinning to specific cpus. std::optional> CpuBinding; /// The optional selected instruction groups. If this is empty the default will be choosen. - std::string InstructionGroups; + std::optional Groups; /// The file where the dump register feature will safe its output to. std::string DumpRegistersOutpath; /// The name of the optimization algorithm. @@ -83,8 +85,8 @@ struct Config { std::optional RequestedNumThreads; /// The selected function id. std::optional FunctionId; - /// The line count of the payload. 0 means default. - unsigned LineCount = 0; + /// The optional line count of the payload. + std::optional LineCount; /// The number of gpus firestarter should stress. Default is -1 means all gpus. int Gpus = 0; /// The matrix size which should be used. 0 means automatic detections. diff --git a/include/firestarter/Config/InstructionGroups.hpp b/include/firestarter/Config/InstructionGroups.hpp new file mode 100644 index 00000000..e6fbc914 --- /dev/null +++ b/include/firestarter/Config/InstructionGroups.hpp @@ -0,0 +1,62 @@ +/****************************************************************************** + * FIRESTARTER - A Processor Stress Test Utility + * Copyright (C) 2024 TU Dresden, Center for Information Services and High + * Performance Computing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Contact: daniel.hackenberg@tu-dresden.de + *****************************************************************************/ + +#pragma once + +#include +#include +#include + +namespace firestarter { + +/// Struct to parse selected from a string. The format is a comma delimited list of instruction value pairs. The values +/// are unsigned integers. +struct InstructionGroups { + InstructionGroups() = default; + + friend auto operator<<(std::ostream& Stream, const InstructionGroups& IGroups) -> std::ostream&; + + /// Parse the instruction group string. It is a comma delimited list of instruction value pairs. The values are + /// unsigned integers. + /// \arg Groups The instruction groups as a string. + [[nodiscard]] static auto fromString(const std::string& Groups) -> InstructionGroups; + + /// The parsed instruction groups + std::vector> Groups; +}; + +inline auto operator<<(std::ostream& Stream, const InstructionGroups& IGroups) -> std::ostream& { + std::stringstream Ss; + + for (auto const& [Key, Value] : IGroups.Groups) { + Ss << Key << ":" << Value << ","; + } + + auto S = Ss.str(); + if (!S.empty()) { + S.pop_back(); + } + + Stream << S; + return Stream; +} + +} // namespace firestarter \ No newline at end of file diff --git a/include/firestarter/Payload/Payload.hpp b/include/firestarter/Payload/Payload.hpp index 1cd64103..97813d76 100644 --- a/include/firestarter/Payload/Payload.hpp +++ b/include/firestarter/Payload/Payload.hpp @@ -22,6 +22,7 @@ #pragma once #include "firestarter/Constants.hpp" +#include "firestarter/Logging/Log.hpp" #include "firestarter/Payload/CompiledPayload.hpp" #include "firestarter/Payload/PayloadSettings.hpp" #include "firestarter/ProcessorInformation.hpp" @@ -104,8 +105,7 @@ class Payload { [[nodiscard]] virtual auto getAvailableInstructions() const -> std::list = 0; /// Print the available instruction groups of this payload - /// \arg Stream The stream to which the message will be saved. - void printAvailableInstructionGroups(std::ostream& Stream) const { + void printAvailableInstructionGroups() const { std::stringstream Ss; for (auto const& Item : getAvailableInstructions()) { @@ -117,8 +117,8 @@ class Payload { S.pop_back(); } - Stream << " available instruction-groups for payload " << name() << ":\n" - << " " << S; + log::info() << " available instruction-groups for payload " << name() << ":\n" + << " " << S; } }; diff --git a/include/firestarter/Platform/PlatformConfig.hpp b/include/firestarter/Platform/PlatformConfig.hpp index c853b0c7..02e8d56f 100644 --- a/include/firestarter/Platform/PlatformConfig.hpp +++ b/include/firestarter/Platform/PlatformConfig.hpp @@ -21,13 +21,13 @@ #pragma once +#include "firestarter/Config/InstructionGroups.hpp" #include "firestarter/Logging/Log.hpp" #include "firestarter/Payload/Payload.hpp" #include "firestarter/ProcessorInformation.hpp" #include #include -#include namespace firestarter::platform { @@ -107,41 +107,18 @@ class PlatformConfig { /// invalid. /// \arg Groups The list of instruction groups that is in the format: multiple INSTRUCTION:VALUE pairs /// comma-seperated. - void selectInstructionGroups(const std::string& Groups) { - const auto Delimiter = ','; - const std::regex Re("^(\\w+):(\\d+)$"); - const auto AvailableInstructionGroups = payload()->getAvailableInstructions(); - - std::stringstream Ss(Groups); - std::vector> PayloadSettings = {}; - - while (Ss.good()) { - std::string Token; - std::smatch M; - std::getline(Ss, Token, Delimiter); - - if (std::regex_match(Token, M, Re)) { - if (std::find(AvailableInstructionGroups.begin(), AvailableInstructionGroups.end(), M[1].str()) == - AvailableInstructionGroups.end()) { - throw std::invalid_argument("Invalid instruction-group: " + M[1].str() + - "\n --run-instruction-groups format: multiple INST:VAL " - "pairs comma-seperated"); - } - auto Num = std::stoul(M[2].str()); - if (Num == 0) { - throw std::invalid_argument("instruction-group VAL may not contain number 0" - "\n --run-instruction-groups format: multiple INST:VAL " - "pairs comma-seperated"); - } - PayloadSettings.emplace_back(M[1].str(), Num); - } else { - throw std::invalid_argument("Invalid symbols in instruction-group: " + Token + + void selectInstructionGroups(const InstructionGroups& Groups) { + const auto& AvailableInstructionGroups = payload()->getAvailableInstructions(); + for (const auto& [Instruction, Value] : Groups.Groups) { + if (std::find(AvailableInstructionGroups.begin(), AvailableInstructionGroups.end(), Instruction) == + AvailableInstructionGroups.end()) { + throw std::invalid_argument("Invalid instruction-group: " + Instruction + "\n --run-instruction-groups format: multiple INST:VAL " "pairs comma-seperated"); } } - settings().selectInstructionGroups(PayloadSettings); + settings().selectInstructionGroups(Groups.Groups); log::info() << " Running custom instruction group: " << Groups; } diff --git a/include/firestarter/ProcessorInformation.hpp b/include/firestarter/ProcessorInformation.hpp index 1cd4c437..6a5db58b 100644 --- a/include/firestarter/ProcessorInformation.hpp +++ b/include/firestarter/ProcessorInformation.hpp @@ -39,8 +39,6 @@ class ProcessorInformation { explicit ProcessorInformation(std::string Architecture); virtual ~ProcessorInformation() = default; - friend auto operator<<(std::ostream& Stream, ProcessorInformation const& ProcessorInfos) -> std::ostream&; - /// Getter for the clockrate in Hz [[nodiscard]] virtual auto clockrate() const -> uint64_t { return Clockrate; } @@ -53,6 +51,9 @@ class ProcessorInformation { /// The model of the processor. With X86 this is the the string of Family, Model and Stepping. [[nodiscard]] virtual auto model() const -> std::string const& = 0; + /// Print the information about this process to a stream. + void print() const; + protected: /// The CPU architecture e.g., x86_64 [[nodiscard]] auto architecture() const -> std::string const& { return Architecture; } @@ -64,9 +65,6 @@ class ProcessorInformation { /// Read the scaling_govenor file of cpu0 on linux and return the contents as a string. [[nodiscard]] static auto scalingGovernor() -> std::string; - /// Print the information about this process to a stream. - [[nodiscard]] auto print(std::ostream& Stream) const -> std::ostream&; - private: /// The CPU vendor i.e., Intel or AMD. std::string Vendor; @@ -84,8 +82,4 @@ class ProcessorInformation { uint64_t Clockrate = 0; }; -inline auto operator<<(std::ostream& Stream, ProcessorInformation const& ProcessorInfos) -> std::ostream& { - return ProcessorInfos.print(Stream); -} - } // namespace firestarter diff --git a/include/firestarter/X86/X86FunctionSelection.hpp b/include/firestarter/X86/X86FunctionSelection.hpp index 7d591c66..3d59982e 100644 --- a/include/firestarter/X86/X86FunctionSelection.hpp +++ b/include/firestarter/X86/X86FunctionSelection.hpp @@ -34,6 +34,7 @@ #include "firestarter/X86/Platform/SandyBridgeEPConfig.hpp" #include "firestarter/X86/Platform/SkylakeConfig.hpp" #include "firestarter/X86/Platform/SkylakeSPConfig.hpp" + #include namespace firestarter::x86 { diff --git a/include/firestarter/X86/X86ProcessorInformation.hpp b/include/firestarter/X86/X86ProcessorInformation.hpp index 553c56e8..b7922a66 100644 --- a/include/firestarter/X86/X86ProcessorInformation.hpp +++ b/include/firestarter/X86/X86ProcessorInformation.hpp @@ -32,8 +32,6 @@ class X86ProcessorInformation final : public ProcessorInformation { public: X86ProcessorInformation(); - friend auto operator<<(std::ostream& Stream, X86ProcessorInformation const& ProcessorInfos) -> std::ostream&; - /// Getter for the list of CPU features [[nodiscard]] auto features() const -> std::list const& override { return this->FeatureList; } /// Getter for the CPU features class from asmjit @@ -81,8 +79,4 @@ class X86ProcessorInformation final : public ProcessorInformation { std::string Model; }; -inline auto operator<<(std::ostream& Stream, X86ProcessorInformation const& ProcessorInfos) -> std::ostream& { - return ProcessorInfos.print(Stream); -} - } // namespace firestarter::x86 \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fbe99350..928ef7f3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,6 +10,7 @@ add_library(firestartercore STATIC firestarter/ProcessorInformation.cpp firestarter/Config/Config.cpp + firestarter/Config/InstructionGroups.cpp firestarter/Config/CpuBind.cpp firestarter/Payload/CompiledPayload.cpp diff --git a/src/firestarter/CPUTopology.cpp b/src/firestarter/CPUTopology.cpp index e0d834a0..dbda519a 100644 --- a/src/firestarter/CPUTopology.cpp +++ b/src/firestarter/CPUTopology.cpp @@ -60,20 +60,20 @@ CPUTopology::CPUTopology() { CPUTopology::~CPUTopology() { hwloc_topology_destroy(Topology); } -void CPUTopology::printSystemSummary(std::ostream& Stream) const { +void CPUTopology::printSystemSummary() const { auto Resouces = homogenousResourceCount(); - Stream << " system summary:\n" - << " number of processors: " << Resouces.NumPackagesTotal << "\n" - << " number of cores (total)): " << Resouces.NumCoresTotal << "\n" - << " (this includes only cores in the cgroup)" - << "\n" - << " number of threads per core: " << Resouces.NumThreadsPerCore << "\n" - << " total number of threads: " << hardwareThreadsInfo().MaxNumThreads << "\n"; + log::info() << " system summary:\n" + << " number of processors: " << Resouces.NumPackagesTotal << "\n" + << " number of cores (total)): " << Resouces.NumCoresTotal << "\n" + << " (this includes only cores in the cgroup)" + << "\n" + << " number of threads per core: " << Resouces.NumThreadsPerCore << "\n" + << " total number of threads: " << hardwareThreadsInfo().MaxNumThreads; } -void CPUTopology::printCacheSummary(std::ostream& Stream) const { - Stream << " Caches:"; +void CPUTopology::printCacheSummary() const { + log::info() << " Caches:"; const std::vector Caches = { HWLOC_OBJ_L1CACHE, HWLOC_OBJ_L1ICACHE, HWLOC_OBJ_L2CACHE, HWLOC_OBJ_L2ICACHE, @@ -86,7 +86,7 @@ void CPUTopology::printCacheSummary(std::ostream& Stream) const { auto Width = hwloc_get_nbobjs_by_type(Topology, Cache); if (Width >= 1) { - Ss << "\n - "; + Ss << " - "; auto* CacheObj = hwloc_get_obj_by_type(Topology, Cache, 0); std::array String{}; @@ -131,7 +131,7 @@ void CPUTopology::printCacheSummary(std::ostream& Stream) const { Ss << "per thread."; } - Stream << Ss.str(); + log::info() << Ss.str(); } } } diff --git a/src/firestarter/Config/Config.cpp b/src/firestarter/Config/Config.cpp index e7d99b33..c144bd72 100644 --- a/src/firestarter/Config/Config.cpp +++ b/src/firestarter/Config/Config.cpp @@ -171,7 +171,7 @@ Config::Config(int Argc, const char** Argv) Parser.add_options("specialized-workloads") ("list-instruction-groups", "List the available instruction groups for the\npayload of the current platform.") ("run-instruction-groups", "Run the payload with the specified\ninstruction groups. GROUPS format: multiple INST:VAL\npairs comma-seperated.", - cxxopts::value()->default_value(""), "GROUPS") + cxxopts::value(), "GROUPS") ("set-line-count", "Set the number of lines for a payload.", cxxopts::value()); @@ -331,7 +331,9 @@ Config::Config(int Argc, const char** Argv) } ListInstructionGroups = static_cast(Options.count("list-instruction-groups")); - InstructionGroups = Options["run-instruction-groups"].as(); + if (static_cast(Options.count("run-instruction-groups"))) { + Groups = InstructionGroups::fromString(Options["run-instruction-groups"].as()); + } if (static_cast(Options.count("set-line-count"))) { LineCount = Options["set-line-count"].as(); } diff --git a/src/firestarter/Config/InstructionGroups.cpp b/src/firestarter/Config/InstructionGroups.cpp new file mode 100644 index 00000000..2abd99e0 --- /dev/null +++ b/src/firestarter/Config/InstructionGroups.cpp @@ -0,0 +1,58 @@ +/****************************************************************************** + * FIRESTARTER - A Processor Stress Test Utility + * Copyright (C) 2024 TU Dresden, Center for Information Services and High + * Performance Computing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Contact: daniel.hackenberg@tu-dresden.de + *****************************************************************************/ + +#include "firestarter/Config/InstructionGroups.hpp" + +#include + +namespace firestarter { + +auto InstructionGroups::fromString(const std::string& Groups) -> InstructionGroups { + const auto Delimiter = ','; + const std::regex Re("^(\\w+):(\\d+)$"); + + std::stringstream Ss(Groups); + std::vector> ParsedGroups; + + while (Ss.good()) { + std::string Token; + std::smatch M; + std::getline(Ss, Token, Delimiter); + + if (std::regex_match(Token, M, Re)) { + auto Num = std::stoul(M[2].str()); + if (Num == 0) { + throw std::invalid_argument("instruction-group VAL may not contain number 0" + "\n --run-instruction-groups format: multiple INST:VAL " + "pairs comma-seperated"); + } + ParsedGroups.emplace_back(M[1].str(), Num); + } else { + throw std::invalid_argument("Invalid symbols in instruction-group: " + Token + + "\n --run-instruction-groups format: multiple INST:VAL " + "pairs comma-seperated"); + } + } + + return InstructionGroups{ParsedGroups}; +} + +} // namespace firestarter \ No newline at end of file diff --git a/src/firestarter/Firestarter.cpp b/src/firestarter/Firestarter.cpp index f945399b..d6bdb5ee 100644 --- a/src/firestarter/Firestarter.cpp +++ b/src/firestarter/Firestarter.cpp @@ -69,19 +69,16 @@ Firestarter::Firestarter(Config&& ProvidedConfig) FunctionSelectionPtr->selectFunction(Cfg.FunctionId, *ProcessorInfos, Topology, Cfg.AllowUnavailablePayload); if (Cfg.ListInstructionGroups) { - std::stringstream Ss; - FunctionPtr->payload()->printAvailableInstructionGroups(Ss); - log::info() << Ss.str(); + FunctionPtr->payload()->printAvailableInstructionGroups(); safeExit(EXIT_SUCCESS); } - - if (!Cfg.InstructionGroups.empty()) { - FunctionPtr->selectInstructionGroups(Cfg.InstructionGroups); + if (Cfg.Groups) { + FunctionPtr->selectInstructionGroups(*Cfg.Groups); } - if (Cfg.LineCount != 0) { - FunctionPtr->settings().setLineCount(Cfg.LineCount); + if (Cfg.LineCount) { + FunctionPtr->settings().setLineCount(*Cfg.LineCount); } if constexpr (firestarter::OptionalFeatures.OptimizationEnabled) { @@ -173,16 +170,10 @@ Firestarter::Firestarter(Config&& ProvidedConfig) FunctionPtr->printCodePathSummary(); - { - std::stringstream Ss; - - Topology.printSystemSummary(Ss); - Ss << "\n"; - Ss << *ProcessorInfos; - Topology.printCacheSummary(Ss); - - log::info() << Ss.str(); - } + Topology.printSystemSummary(); + log::info(); + ProcessorInfos->print(); + Topology.printCacheSummary(); Affinity.printThreadSummary(Topology); diff --git a/src/firestarter/ProcessorInformation.cpp b/src/firestarter/ProcessorInformation.cpp index c7c9c115..e1ea9df8 100644 --- a/src/firestarter/ProcessorInformation.cpp +++ b/src/firestarter/ProcessorInformation.cpp @@ -20,6 +20,7 @@ *****************************************************************************/ #include "firestarter/ProcessorInformation.hpp" +#include "firestarter/Firestarter.hpp" #include "firestarter/Logging/Log.hpp" #include @@ -32,22 +33,20 @@ namespace firestarter { -auto ProcessorInformation::print(std::ostream& Stream) const -> std::ostream& { +void ProcessorInformation::print() const { std::stringstream Ss; for (auto const& Entry : features()) { Ss << Entry << " "; } - Stream << " processor characteristics:\n" - << " architecture: " << architecture() << "\n" - << " vendor: " << vendor() << "\n" - << " processor-name: " << processorName() << "\n" - << " model: " << model() << "\n" - << " frequency: " << clockrate() / 1000000 << " MHz\n" - << " supported features: " << Ss.str() << "\n"; - - return Stream; + log::info() << " processor characteristics:\n" + << " architecture: " << architecture() << "\n" + << " vendor: " << vendor() << "\n" + << " processor-name: " << processorName() << "\n" + << " model: " << model() << "\n" + << " frequency: " << clockrate() / 1000000 << " MHz\n" + << " supported features: " << Ss.str(); } ProcessorInformation::ProcessorInformation(std::string Architecture) diff --git a/test/DumpCPUTopology/Main.cpp b/test/DumpCPUTopology/Main.cpp index 4b1a0671..314e5d39 100644 --- a/test/DumpCPUTopology/Main.cpp +++ b/test/DumpCPUTopology/Main.cpp @@ -29,12 +29,8 @@ auto main(int /*argc*/, const char** /*argv*/) -> int { firestarter::CPUTopology Topology; - { - std::stringstream Ss; - Topology.printSystemSummary(Ss); - Topology.printCacheSummary(Ss); - firestarter::log::info() << Ss.str(); - } + Topology.printSystemSummary(); + Topology.printCacheSummary(); { auto ICacheSize = Topology.instructionCacheSize(); From 31fe3861015fd319f7430aabc4bd0a3f057998e2 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Wed, 11 Dec 2024 01:00:41 +0100 Subject: [PATCH 14/31] cleanup --- include/firestarter/ProcessorInformation.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/firestarter/ProcessorInformation.hpp b/include/firestarter/ProcessorInformation.hpp index 6a5db58b..d5e2173e 100644 --- a/include/firestarter/ProcessorInformation.hpp +++ b/include/firestarter/ProcessorInformation.hpp @@ -23,7 +23,6 @@ #include #include -#include #include #include From ba57ac954108666ca5771da7e7d2d3f1023a0031 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Wed, 11 Dec 2024 01:34:18 +0100 Subject: [PATCH 15/31] refactor instruction groups --- .../firestarter/Config/InstructionGroups.hpp | 10 ++++ include/firestarter/Firestarter.hpp | 2 +- .../Optimizer/Problem/CLIArgumentProblem.hpp | 9 ++-- .../firestarter/Payload/PayloadSettings.hpp | 51 ++++--------------- .../firestarter/Platform/PlatformConfig.hpp | 2 +- .../X86/Platform/BulldozerConfig.hpp | 3 +- .../X86/Platform/HaswellConfig.hpp | 3 +- .../X86/Platform/HaswellEPConfig.hpp | 3 +- .../X86/Platform/KnightsLandingConfig.hpp | 3 +- .../firestarter/X86/Platform/NaplesConfig.hpp | 3 +- .../X86/Platform/NehalemConfig.hpp | 3 +- .../X86/Platform/NehalemEPConfig.hpp | 3 +- .../firestarter/X86/Platform/RomeConfig.hpp | 5 +- .../X86/Platform/SandyBridgeConfig.hpp | 3 +- .../X86/Platform/SandyBridgeEPConfig.hpp | 3 +- .../X86/Platform/SkylakeConfig.hpp | 18 ++++--- .../X86/Platform/SkylakeSPConfig.hpp | 20 ++++---- src/firestarter/Firestarter.cpp | 6 +-- src/firestarter/FunctionSelection.cpp | 2 +- src/firestarter/Payload/PayloadSettings.cpp | 6 +-- test/DumpPayloads/Main.cpp | 9 ++-- 21 files changed, 78 insertions(+), 89 deletions(-) diff --git a/include/firestarter/Config/InstructionGroups.hpp b/include/firestarter/Config/InstructionGroups.hpp index e6fbc914..6712774b 100644 --- a/include/firestarter/Config/InstructionGroups.hpp +++ b/include/firestarter/Config/InstructionGroups.hpp @@ -39,6 +39,16 @@ struct InstructionGroups { /// \arg Groups The instruction groups as a string. [[nodiscard]] static auto fromString(const std::string& Groups) -> InstructionGroups; + /// The vector of used instructions that are saved in the instruction groups + [[nodiscard]] auto intructions() const -> std::vector { + std::vector Items; + Items.reserve(Groups.size()); + for (auto const& Pair : Groups) { + Items.push_back(Pair.first); + } + return Items; + } + /// The parsed instruction groups std::vector> Groups; }; diff --git a/include/firestarter/Firestarter.hpp b/include/firestarter/Firestarter.hpp index 4be5b1a6..d5fd2595 100644 --- a/include/firestarter/Firestarter.hpp +++ b/include/firestarter/Firestarter.hpp @@ -137,7 +137,7 @@ class Firestarter { /// Set the load workers to the ThreadWork state. /// \arg Setting The new setting to switch to. - void signalSwitch(std::vector> const& Setting) { + void signalSwitch(const InstructionGroups& Setting) { struct SwitchLoad { static void func() { LoadVar = LoadThreadWorkType::LoadSwitch; }; }; diff --git a/include/firestarter/Optimizer/Problem/CLIArgumentProblem.hpp b/include/firestarter/Optimizer/Problem/CLIArgumentProblem.hpp index 4335a4f9..0cfc236e 100644 --- a/include/firestarter/Optimizer/Problem/CLIArgumentProblem.hpp +++ b/include/firestarter/Optimizer/Problem/CLIArgumentProblem.hpp @@ -21,6 +21,7 @@ #pragma once +#include "firestarter/Config/InstructionGroups.hpp" #include "firestarter/Measurement/MeasurementWorker.hpp" #include "firestarter/Optimizer/Problem.hpp" @@ -38,7 +39,7 @@ class CLIArgumentProblem final : public firestarter::optimizer::Problem { private: /// The function which takes instruction groups and switches the payload in the high load function to the supplied /// ones. - std::function> const&)> ChangePayloadFunction; + std::function ChangePayloadFunction; /// The shared pointer to the measurement infrastructure which will be used to get metric values. std::shared_ptr MeasurementWorker; /// The metrics that are used in the optimization. They may have a dash at the start to allow them to be changed from @@ -65,7 +66,7 @@ class CLIArgumentProblem final : public firestarter::optimizer::Problem { /// \arg StartDelta The time to skip from the measurement start /// \arg StopDelta The time to skip from the measurement stop /// \arg InstructionGroups The vector of instruction that is used in the optimization for the payload. - CLIArgumentProblem(std::function> const&)>&& ChangePayloadFunction, + CLIArgumentProblem(std::function&& ChangePayloadFunction, std::shared_ptr MeasurementWorker, std::vector const& Metrics, std::chrono::seconds Timeout, std::chrono::milliseconds StartDelta, std::chrono::milliseconds StopDelta, @@ -98,7 +99,7 @@ class CLIArgumentProblem final : public firestarter::optimizer::Problem { for (; It1 != InstructionGroups.end(); ++It1, ++It2) { Payload.emplace_back(*It1, *It2); } - ChangePayloadFunction(Payload); + ChangePayloadFunction(firestarter::InstructionGroups{Payload}); // start the measurement // NOTE: starting the measurement must happen after switching to not @@ -111,7 +112,7 @@ class CLIArgumentProblem final : public firestarter::optimizer::Problem { // TODO(Issue #82): This is an ugly workaround for the ipc-estimate metric. // Changing the payload triggers a write of the iteration counter of // the last payload, which we use to estimate the ipc. - ChangePayloadFunction(Payload); + ChangePayloadFunction(firestarter::InstructionGroups{Payload}); // return the results return MeasurementWorker->getValues(StartDelta, StopDelta); diff --git a/include/firestarter/Payload/PayloadSettings.hpp b/include/firestarter/Payload/PayloadSettings.hpp index 68e617a8..c1e50807 100644 --- a/include/firestarter/Payload/PayloadSettings.hpp +++ b/include/firestarter/Payload/PayloadSettings.hpp @@ -21,12 +21,12 @@ #pragma once +#include "firestarter/Config/InstructionGroups.hpp" #include #include #include #include #include -#include #include #include @@ -34,9 +34,6 @@ namespace firestarter::payload { /// This class represents the settings that can be changed in the high load routine of a payload. struct PayloadSettings { -public: - using InstructionWithProportion = std::pair; - private: /// The number of threads for which this payload is available. Multiple ones may exsists. The PayloadSettings are /// concreate once this is set to contain only one element. @@ -56,7 +53,7 @@ struct PayloadSettings { /// This represents the instructions in combination with the number of times they should appear in the generated /// sequence. - std::vector InstructionGroups; + InstructionGroups Groups; /// Get the number of items in the sequence that start with a given string. /// \arg Sequence The sequence that is analyzed. @@ -69,20 +66,19 @@ struct PayloadSettings { PayloadSettings() = delete; PayloadSettings(std::initializer_list Threads, std::initializer_list DataCacheBufferSize, - unsigned RamBufferSize, unsigned Lines, std::vector&& InstructionGroups) + unsigned RamBufferSize, unsigned Lines, InstructionGroups&& Groups) : Threads(Threads) , DataCacheBufferSize(DataCacheBufferSize) , RamBufferSize(RamBufferSize) , Lines(Lines) - , InstructionGroups(std::move(InstructionGroups)) {} + , Groups(std::move(Groups)) {} /// Generate a sequence of items interleaved with one another based on a supplied number how many times each items /// should appear in the resulting sequence. /// \arg Proportion The mapping of items defined by a string and the number of times this item should apear in the /// resuling sequence. /// \returns The sequence that is generated from the supplied propotions - [[nodiscard]] static auto generateSequence(const std::vector& Proportion) - -> std::vector; + [[nodiscard]] static auto generateSequence(const InstructionGroups& Proportion) -> std::vector; /// Get the number of items in the sequence that start with "L2". /// \arg Sequence The sequence that is analyzed. @@ -214,38 +210,11 @@ struct PayloadSettings { [[nodiscard]] auto linesPerThread() const -> auto{ return Lines / thread(); } /// The vector of instruction groups with proportions. - [[nodiscard]] auto instructionGroups() const -> const auto& { return InstructionGroups; } + [[nodiscard]] auto groups() const -> const auto& { return Groups; } /// Generate a sequence of items interleaved with one another based on the instruction groups. /// \returns The sequence that is generated from the supplied propotions in the instruction groups. - [[nodiscard]] auto sequence() const -> std::vector { return generateSequence(instructionGroups()); } - - /// The vector of used instructions that are saved in the instruction groups - [[nodiscard]] auto instructionGroupItems() const -> std::vector { - std::vector Items; - Items.reserve(InstructionGroups.size()); - for (auto const& Pair : InstructionGroups) { - Items.push_back(Pair.first); - } - return Items; - } - - /// Get the string that represents the instructions in combination with the number of times they should appear in the - /// sequence. - [[nodiscard]] auto getInstructionGroupsString() const -> std::string { - std::stringstream Ss; - - for (auto const& [Name, Value] : InstructionGroups) { - Ss << Name << ":" << Value << ","; - } - - auto Str = Ss.str(); - if (!Str.empty()) { - Str.pop_back(); - } - - return Str; - } + [[nodiscard]] auto sequence() const -> std::vector { return generateSequence(groups()); } /// Make the settings concreate. /// \arg InstructionCacheSize The detected size of the instructions cache. @@ -256,10 +225,8 @@ struct PayloadSettings { } /// Save the supplied instruction groups with their proportion in the payload settings. - /// \arg InstructionGroups The vector with pairs of instructions and proportions - void selectInstructionGroups(std::vector const& InstructionGroups) { - this->InstructionGroups = InstructionGroups; - } + /// \arg Groups The vector with pairs of instructions and proportions + void selectInstructionGroups(InstructionGroups const& Groups) { this->Groups = Groups; } /// Save the line count in the payload settings. void setLineCount(unsigned LineCount) { this->Lines = LineCount; } diff --git a/include/firestarter/Platform/PlatformConfig.hpp b/include/firestarter/Platform/PlatformConfig.hpp index 02e8d56f..e990c3ae 100644 --- a/include/firestarter/Platform/PlatformConfig.hpp +++ b/include/firestarter/Platform/PlatformConfig.hpp @@ -118,7 +118,7 @@ class PlatformConfig { } } - settings().selectInstructionGroups(Groups.Groups); + settings().selectInstructionGroups(Groups); log::info() << " Running custom instruction group: " << Groups; } diff --git a/include/firestarter/X86/Platform/BulldozerConfig.hpp b/include/firestarter/X86/Platform/BulldozerConfig.hpp index 1965d9ef..a1496e20 100644 --- a/include/firestarter/X86/Platform/BulldozerConfig.hpp +++ b/include/firestarter/X86/Platform/BulldozerConfig.hpp @@ -34,7 +34,8 @@ class BulldozerConfig final : public X86PlatformConfig { firestarter::payload::PayloadSettings( /*Threads=*/{1}, /*DataCacheBufferSize=*/{16384, 1048576, 786432}, /*RamBufferSize=*/104857600, /*Lines=*/1536, - /*InstructionGroups=*/{{"RAM_L", 1}, {"L3_L", 1}, {"L2_LS", 5}, {"L1_L", 90}, {"REG", 45}}), + /*Groups=*/ + InstructionGroups{{{"RAM_L", 1}, {"L3_L", 1}, {"L2_LS", 5}, {"L1_L", 90}, {"REG", 45}}}), /*Payload=*/std::make_shared()) {} }; } // namespace firestarter::x86::platform diff --git a/include/firestarter/X86/Platform/HaswellConfig.hpp b/include/firestarter/X86/Platform/HaswellConfig.hpp index 82820a42..e117b20d 100644 --- a/include/firestarter/X86/Platform/HaswellConfig.hpp +++ b/include/firestarter/X86/Platform/HaswellConfig.hpp @@ -34,7 +34,8 @@ class HaswellConfig final : public X86PlatformConfig { firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 1572864}, /*RamBufferSize=*/104857600, /*Lines=*/1536, - /*InstructionGroups=*/{{"RAM_L", 2}, {"L3_LS", 3}, {"L2_LS", 9}, {"L1_LS", 90}, {"REG", 40}}), + /*Groups=*/ + InstructionGroups{{{"RAM_L", 2}, {"L3_LS", 3}, {"L2_LS", 9}, {"L1_LS", 90}, {"REG", 40}}}), /*Payload=*/std::make_shared()) {} }; } // namespace firestarter::x86::platform diff --git a/include/firestarter/X86/Platform/HaswellEPConfig.hpp b/include/firestarter/X86/Platform/HaswellEPConfig.hpp index 1ff81e64..d0b7f014 100644 --- a/include/firestarter/X86/Platform/HaswellEPConfig.hpp +++ b/include/firestarter/X86/Platform/HaswellEPConfig.hpp @@ -34,7 +34,8 @@ class HaswellEPConfig final : public X86PlatformConfig { firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 2621440}, /*RamBufferSize=*/104857600, /*Lines=*/1536, - /*InstructionGroups=*/{{"RAM_L", 8}, {"L3_LS", 1}, {"L2_LS", 29}, {"L1_LS", 100}, {"REG", 100}}), + /*Groups=*/ + InstructionGroups{{{"RAM_L", 8}, {"L3_LS", 1}, {"L2_LS", 29}, {"L1_LS", 100}, {"REG", 100}}}), /*Payload=*/std::make_shared()) {} }; } // namespace firestarter::x86::platform diff --git a/include/firestarter/X86/Platform/KnightsLandingConfig.hpp b/include/firestarter/X86/Platform/KnightsLandingConfig.hpp index 462cdc3b..e46ebdc5 100644 --- a/include/firestarter/X86/Platform/KnightsLandingConfig.hpp +++ b/include/firestarter/X86/Platform/KnightsLandingConfig.hpp @@ -33,7 +33,8 @@ class KnightsLandingConfig final : public X86PlatformConfig { firestarter::payload::PayloadSettings( /*Threads=*/{4}, /*DataCacheBufferSize=*/{32768, 524288, 236279125}, /*RamBufferSize=*/26214400, /*Lines=*/1536, - /*InstructionGroups=*/{{"RAM_P", 3}, {"L2_S", 8}, {"L1_L", 40}, {"REG", 10}}), + /*Groups=*/ + InstructionGroups{{{"RAM_P", 3}, {"L2_S", 8}, {"L1_L", 40}, {"REG", 10}}}), /*Payload=*/std::make_shared()) {} }; } // namespace firestarter::x86::platform diff --git a/include/firestarter/X86/Platform/NaplesConfig.hpp b/include/firestarter/X86/Platform/NaplesConfig.hpp index 7ea5bd0e..5bbb25f5 100644 --- a/include/firestarter/X86/Platform/NaplesConfig.hpp +++ b/include/firestarter/X86/Platform/NaplesConfig.hpp @@ -34,7 +34,8 @@ class NaplesConfig final : public X86PlatformConfig { firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{65536, 524288, 2097152}, /*RamBufferSize=*/104857600, /*Lines=*/1536, - /*InstructionGroups=*/{{"RAM_L", 3}, {"L3_L", 14}, {"L2_L", 75}, {"L1_LS", 81}, {"REG", 100}}), + /*Groups=*/ + InstructionGroups{{{"RAM_L", 3}, {"L3_L", 14}, {"L2_L", 75}, {"L1_LS", 81}, {"REG", 100}}}), /*Payload=*/std::make_shared()) {} }; } // namespace firestarter::x86::platform diff --git a/include/firestarter/X86/Platform/NehalemConfig.hpp b/include/firestarter/X86/Platform/NehalemConfig.hpp index 67ea2dfc..c1f0e3b3 100644 --- a/include/firestarter/X86/Platform/NehalemConfig.hpp +++ b/include/firestarter/X86/Platform/NehalemConfig.hpp @@ -33,7 +33,8 @@ class NehalemConfig final : public X86PlatformConfig { /*Settings=*/ firestarter::payload::PayloadSettings(/*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 1572864}, /*RamBufferSize=*/104857600, /*Lines=*/1536, - /*InstructionGroups=*/{{"RAM_P", 1}, {"L1_LS", 70}, {"REG", 2}}), + /*Groups=*/ + InstructionGroups{{{"RAM_P", 1}, {"L1_LS", 70}, {"REG", 2}}}), /*Payload=*/std::make_shared()) {} }; } // namespace firestarter::x86::platform diff --git a/include/firestarter/X86/Platform/NehalemEPConfig.hpp b/include/firestarter/X86/Platform/NehalemEPConfig.hpp index 9ea1641c..c02e7f47 100644 --- a/include/firestarter/X86/Platform/NehalemEPConfig.hpp +++ b/include/firestarter/X86/Platform/NehalemEPConfig.hpp @@ -33,7 +33,8 @@ class NehalemEPConfig final : public X86PlatformConfig { firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 2097152}, /*RamBufferSize=*/104857600, /*Lines=*/1536, - /*InstructionGroups=*/{{"RAM_P", 1}, {"L1_LS", 60}, {"REG", 2}}), + /*Groups=*/ + InstructionGroups{{{"RAM_P", 1}, {"L1_LS", 60}, {"REG", 2}}}), /*Payload=*/std::make_shared()) {} }; } // namespace firestarter::x86::platform diff --git a/include/firestarter/X86/Platform/RomeConfig.hpp b/include/firestarter/X86/Platform/RomeConfig.hpp index 189858fb..5a2d04e4 100644 --- a/include/firestarter/X86/Platform/RomeConfig.hpp +++ b/include/firestarter/X86/Platform/RomeConfig.hpp @@ -34,8 +34,9 @@ class RomeConfig final : public X86PlatformConfig { firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 524288, 2097152}, /*RamBufferSize=*/104857600, /*Lines=*/1536, - /*InstructionGroups=*/ - {{"RAM_L", 10}, {"L3_L", 25}, {"L2_L", 91}, {"L1_2LS_256", 72}, {"L1_LS_256", 82}, {"REG", 75}}), + /*Groups=*/ + InstructionGroups{ + {{"RAM_L", 10}, {"L3_L", 25}, {"L2_L", 91}, {"L1_2LS_256", 72}, {"L1_LS_256", 82}, {"REG", 75}}}), /*Payload=*/std::make_shared()) {} }; } // namespace firestarter::x86::platform diff --git a/include/firestarter/X86/Platform/SandyBridgeConfig.hpp b/include/firestarter/X86/Platform/SandyBridgeConfig.hpp index 3198d25b..50fd8a00 100644 --- a/include/firestarter/X86/Platform/SandyBridgeConfig.hpp +++ b/include/firestarter/X86/Platform/SandyBridgeConfig.hpp @@ -34,7 +34,8 @@ class SandyBridgeConfig final : public X86PlatformConfig { firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 1572864}, /*RamBufferSize=*/104857600, /*Lines=*/1536, - /*InstructionGroups=*/{{"RAM_L", 2}, {"L3_LS", 4}, {"L2_LS", 10}, {"L1_LS", 90}, {"REG", 45}}), + /*Groups=*/ + InstructionGroups{{{"RAM_L", 2}, {"L3_LS", 4}, {"L2_LS", 10}, {"L1_LS", 90}, {"REG", 45}}}), /*Payload=*/std::make_shared()) {} }; } // namespace firestarter::x86::platform diff --git a/include/firestarter/X86/Platform/SandyBridgeEPConfig.hpp b/include/firestarter/X86/Platform/SandyBridgeEPConfig.hpp index bcc96afb..5f6ec9ce 100644 --- a/include/firestarter/X86/Platform/SandyBridgeEPConfig.hpp +++ b/include/firestarter/X86/Platform/SandyBridgeEPConfig.hpp @@ -34,7 +34,8 @@ class SandyBridgeEPConfig final : public X86PlatformConfig { firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 2621440}, /*RamBufferSize=*/104857600, /*Lines=*/1536, - /*InstructionGroups=*/{{"RAM_L", 3}, {"L3_LS", 2}, {"L2_LS", 10}, {"L1_LS", 90}, {"REG", 30}}), + /*Groups=*/ + InstructionGroups{{{"RAM_L", 3}, {"L3_LS", 2}, {"L2_LS", 10}, {"L1_LS", 90}, {"REG", 30}}}), /*Payload=*/std::make_shared()) {} }; } // namespace firestarter::x86::platform \ No newline at end of file diff --git a/include/firestarter/X86/Platform/SkylakeConfig.hpp b/include/firestarter/X86/Platform/SkylakeConfig.hpp index ed047f72..843151db 100644 --- a/include/firestarter/X86/Platform/SkylakeConfig.hpp +++ b/include/firestarter/X86/Platform/SkylakeConfig.hpp @@ -28,13 +28,15 @@ namespace firestarter::x86::platform { class SkylakeConfig final : public X86PlatformConfig { public: SkylakeConfig() noexcept - : X86PlatformConfig(/*Name=*/"SKL_COREI", /*Family=*/6, /*Models=*/{78, 94}, - /*Settings=*/ - firestarter::payload::PayloadSettings( - /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 1572864}, - /*RamBufferSize=*/104857600, /*Lines=*/1536, - /*InstructionGroups=*/ - {{"RAM_L", 3}, {"L3_LS_256", 5}, {"L2_LS_256", 18}, {"L1_2LS_256", 78}, {"REG", 40}}), - /*Payload=*/std::make_shared()) {} + : X86PlatformConfig( + /*Name=*/"SKL_COREI", /*Family=*/6, /*Models=*/{78, 94}, + /*Settings=*/ + firestarter::payload::PayloadSettings( + /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 1572864}, + /*RamBufferSize=*/104857600, /*Lines=*/1536, + /*Groups=*/ + InstructionGroups{ + {{"RAM_L", 3}, {"L3_LS_256", 5}, {"L2_LS_256", 18}, {"L1_2LS_256", 78}, {"REG", 40}}}), + /*Payload=*/std::make_shared()) {} }; } // namespace firestarter::x86::platform \ No newline at end of file diff --git a/include/firestarter/X86/Platform/SkylakeSPConfig.hpp b/include/firestarter/X86/Platform/SkylakeSPConfig.hpp index 3564e033..c3b50c13 100644 --- a/include/firestarter/X86/Platform/SkylakeSPConfig.hpp +++ b/include/firestarter/X86/Platform/SkylakeSPConfig.hpp @@ -33,16 +33,16 @@ class SkylakeSPConfig final : public X86PlatformConfig { firestarter::payload::PayloadSettings(/*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 1048576, 1441792}, /*RamBufferSize=*/1048576000, /*Lines=*/1536, - /*InstructionGroups=*/ - {{"RAM_S", 3}, - {"RAM_P", 1}, - {"L3_S", 1}, - {"L3_P", 1}, - {"L2_S", 4}, - {"L2_L", 70}, - {"L1_S", 0}, - {"L1_L", 40}, - {"REG", 140}}), + /*Groups=*/ + InstructionGroups{{{"RAM_S", 3}, + {"RAM_P", 1}, + {"L3_S", 1}, + {"L3_P", 1}, + {"L2_S", 4}, + {"L2_L", 70}, + {"L1_S", 0}, + {"L1_L", 40}, + {"REG", 140}}}), /*Payload=*/std::make_shared()) {} }; } // namespace firestarter::x86::platform diff --git a/src/firestarter/Firestarter.cpp b/src/firestarter/Firestarter.cpp index d6bdb5ee..0d77ccb0 100644 --- a/src/firestarter/Firestarter.cpp +++ b/src/firestarter/Firestarter.cpp @@ -117,7 +117,7 @@ Firestarter::Firestarter(Config&& ProvidedConfig) } if (Cfg.Optimize) { - auto ApplySettings = [this](std::vector> const& Setting) { + auto ApplySettings = [this](InstructionGroups const& Setting) { using Clock = std::chrono::high_resolution_clock; auto Start = Clock::now(); @@ -153,7 +153,7 @@ Firestarter::Firestarter(Config&& ProvidedConfig) auto Prob = std::make_shared( std::move(ApplySettings), MeasurementWorker, Cfg.OptimizationMetrics, Cfg.EvaluationDuration, Cfg.StartDelta, - Cfg.StopDelta, FunctionPtr->settings().instructionGroupItems()); + Cfg.StopDelta, FunctionPtr->settings().groups().intructions()); Population = std::make_unique(std::move(Prob)); @@ -224,7 +224,7 @@ void Firestarter::mainThread() { Firestarter::Optimizer->join(); Firestarter::Optimizer.reset(); - auto PayloadItems = FunctionPtr->settings().instructionGroupItems(); + auto PayloadItems = FunctionPtr->settings().groups().intructions(); firestarter::optimizer::History::save(Cfg.OptimizeOutfile, StartTime, PayloadItems, Cfg.Argc, Cfg.Argv); diff --git a/src/firestarter/FunctionSelection.cpp b/src/firestarter/FunctionSelection.cpp index 57bedc5d..14a8d735 100644 --- a/src/firestarter/FunctionSelection.cpp +++ b/src/firestarter/FunctionSelection.cpp @@ -140,7 +140,7 @@ void FunctionSelection::printFunctionSummary(const ProcessorInformation& Process for (const auto& Platform : platform::PlatformConfigAndThreads::fromPlatformConfigs(platformConfigs())) { const char* Available = (Platform.Config->isAvailable(ProcessorInfos) || ForceYes) ? "yes" : "no"; const auto& FunctionName = Platform.Config->functionName(Platform.ThreadCount); - const auto& InstructionGroupsString = Platform.Config->settings().getInstructionGroupsString(); + const auto& InstructionGroupsString = Platform.Config->settings().groups(); log::info() << " " << std::right << std::setw(4) << Id << " | " << std::left << std::setw(30) << FunctionName << " | " << std::left << std::setw(24) << Available << " | " << InstructionGroupsString; diff --git a/src/firestarter/Payload/PayloadSettings.cpp b/src/firestarter/Payload/PayloadSettings.cpp index 12d8f41a..612e62d6 100644 --- a/src/firestarter/Payload/PayloadSettings.cpp +++ b/src/firestarter/Payload/PayloadSettings.cpp @@ -20,6 +20,7 @@ *****************************************************************************/ #include "firestarter/Payload/PayloadSettings.hpp" +#include "firestarter/Config/InstructionGroups.hpp" #include #include @@ -39,9 +40,8 @@ auto PayloadSettings::getSequenceStartCount(const std::vector& Sequ return I; } -auto PayloadSettings::generateSequence(std::vector const& Proportions) - -> std::vector { - std::vector> Prop = Proportions; +auto PayloadSettings::generateSequence(InstructionGroups const& Proportions) -> std::vector { + std::vector> Prop = Proportions.Groups; Prop.erase(std::remove_if(Prop.begin(), Prop.end(), [](auto const& Pair) { return Pair.second == 0; }), Prop.end()); diff --git a/test/DumpPayloads/Main.cpp b/test/DumpPayloads/Main.cpp index 5dd086de..329a6ad4 100644 --- a/test/DumpPayloads/Main.cpp +++ b/test/DumpPayloads/Main.cpp @@ -31,13 +31,12 @@ namespace { /// Take a list of instructions and return a list with a pair containing the each instruction in the first element of /// the pair and a one in the second. -auto oneEach(const std::list& Instructions) - -> std::vector { - std::vector OneEach; +auto oneEach(const std::list& Instructions) -> firestarter::InstructionGroups { + std::vector> OneEach; for (const auto& Instruction : Instructions) { OneEach.emplace_back(Instruction, 1); } - return OneEach; + return firestarter::InstructionGroups{OneEach}; } /// Dump the generated assembler code of the payload with some given settings. Each item is printed once. @@ -48,7 +47,7 @@ void dumpPayload(firestarter::payload::Payload& PayloadPtr) { /*DataCacheBufferSize=*/{32768, 1048576, 1441792}, /*RamBufferSize=*/1048576000, /*Lines=*/3 * Instuctions.size(), - /*InstructionGroups=*/oneEach(Instuctions)); + /*Groups=*/oneEach(Instuctions)); (void)PayloadPtr.compilePayload(Settings, /*DumpRegisters=*/false, /*ErrorDetection=*/false, /*PrintAssembler=*/true); From dee1b4799a7635176008309705a1419db36b0a28 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Wed, 11 Dec 2024 11:44:32 +0100 Subject: [PATCH 16/31] use instruction groups type in more places --- .../firestarter/Config/InstructionGroups.hpp | 29 ++++++++++++------- .../Optimizer/Problem/CLIArgumentProblem.hpp | 24 ++++++--------- .../firestarter/Platform/PlatformConfig.hpp | 2 +- src/firestarter/Config/InstructionGroups.cpp | 25 ++++++++++++++++ src/firestarter/Payload/PayloadSettings.cpp | 2 +- 5 files changed, 55 insertions(+), 27 deletions(-) diff --git a/include/firestarter/Config/InstructionGroups.hpp b/include/firestarter/Config/InstructionGroups.hpp index 6712774b..6eb5b4da 100644 --- a/include/firestarter/Config/InstructionGroups.hpp +++ b/include/firestarter/Config/InstructionGroups.hpp @@ -23,6 +23,7 @@ #include #include +#include #include namespace firestarter { @@ -30,8 +31,15 @@ namespace firestarter { /// Struct to parse selected from a string. The format is a comma delimited list of instruction value pairs. The values /// are unsigned integers. struct InstructionGroups { + using InternalType = std::vector>; + InstructionGroups() = default; + explicit InstructionGroups(InternalType Groups) + : Groups(std::move(Groups)) {} + + explicit operator const InternalType&() const noexcept { return Groups; } + friend auto operator<<(std::ostream& Stream, const InstructionGroups& IGroups) -> std::ostream&; /// Parse the instruction group string. It is a comma delimited list of instruction value pairs. The values are @@ -39,24 +47,25 @@ struct InstructionGroups { /// \arg Groups The instruction groups as a string. [[nodiscard]] static auto fromString(const std::string& Groups) -> InstructionGroups; + /// Combine instructions and values for these instructions into the combined instruction groups. + /// \arg Instructions The vector of instructions + /// \arg Values The vector of values + /// \returns The combined instruction groups + [[nodiscard]] static auto fromInstructionAndValues(const std::vector& Instructions, + const std::vector& Values) -> InstructionGroups; + /// The vector of used instructions that are saved in the instruction groups - [[nodiscard]] auto intructions() const -> std::vector { - std::vector Items; - Items.reserve(Groups.size()); - for (auto const& Pair : Groups) { - Items.push_back(Pair.first); - } - return Items; - } + [[nodiscard]] auto intructions() const -> std::vector; +private: /// The parsed instruction groups std::vector> Groups; }; -inline auto operator<<(std::ostream& Stream, const InstructionGroups& IGroups) -> std::ostream& { +inline auto operator<<(std::ostream& Stream, const InstructionGroups& Groups) -> std::ostream& { std::stringstream Ss; - for (auto const& [Key, Value] : IGroups.Groups) { + for (auto const& [Key, Value] : static_cast(Groups)) { Ss << Key << ":" << Value << ","; } diff --git a/include/firestarter/Optimizer/Problem/CLIArgumentProblem.hpp b/include/firestarter/Optimizer/Problem/CLIArgumentProblem.hpp index 0cfc236e..59da7b23 100644 --- a/include/firestarter/Optimizer/Problem/CLIArgumentProblem.hpp +++ b/include/firestarter/Optimizer/Problem/CLIArgumentProblem.hpp @@ -52,7 +52,7 @@ class CLIArgumentProblem final : public firestarter::optimizer::Problem { /// The time to skip from the measurement stop std::chrono::milliseconds StopDelta; /// The vector of instruction that is used in the optimization for the payload. - std::vector InstructionGroups; + std::vector Instructions; public: /// Constructor for the problem of optimizing firestarter on the fly. @@ -65,19 +65,19 @@ class CLIArgumentProblem final : public firestarter::optimizer::Problem { /// \arg Timeout The duration of the measurement. /// \arg StartDelta The time to skip from the measurement start /// \arg StopDelta The time to skip from the measurement stop - /// \arg InstructionGroups The vector of instruction that is used in the optimization for the payload. + /// \arg Instructions The vector of instruction that is used in the optimization for the payload. CLIArgumentProblem(std::function&& ChangePayloadFunction, std::shared_ptr MeasurementWorker, std::vector const& Metrics, std::chrono::seconds Timeout, std::chrono::milliseconds StartDelta, std::chrono::milliseconds StopDelta, - std::vector InstructionGroups) + std::vector Instructions) : ChangePayloadFunction(std::move(ChangePayloadFunction)) , MeasurementWorker(std::move(MeasurementWorker)) , Metrics(Metrics) , Timeout(Timeout) , StartDelta(StartDelta) , StopDelta(StopDelta) - , InstructionGroups(std::move(InstructionGroups)) { + , Instructions(std::move(Instructions)) { assert(!Metrics.empty()); } @@ -91,15 +91,10 @@ class CLIArgumentProblem final : public firestarter::optimizer::Problem { // increment evaluation idx incrementFevals(); + const auto Groups = firestarter::InstructionGroups::fromInstructionAndValues(Instructions, Individual); + // change the payload - assert(InstructionGroups.size() == Individual.size()); - std::vector> Payload = {}; - auto It1 = InstructionGroups.begin(); - auto It2 = Individual.begin(); - for (; It1 != InstructionGroups.end(); ++It1, ++It2) { - Payload.emplace_back(*It1, *It2); - } - ChangePayloadFunction(firestarter::InstructionGroups{Payload}); + ChangePayloadFunction(Groups); // start the measurement // NOTE: starting the measurement must happen after switching to not @@ -112,7 +107,7 @@ class CLIArgumentProblem final : public firestarter::optimizer::Problem { // TODO(Issue #82): This is an ugly workaround for the ipc-estimate metric. // Changing the payload triggers a write of the iteration counter of // the last payload, which we use to estimate the ipc. - ChangePayloadFunction(firestarter::InstructionGroups{Payload}); + ChangePayloadFunction(Groups); // return the results return MeasurementWorker->getValues(StartDelta, StopDelta); @@ -156,8 +151,7 @@ class CLIArgumentProblem final : public firestarter::optimizer::Problem { /// Get the bounds of the problem. We currently set these bounds fix to a range from 0 to 100 for every instruction. /// \returns A vector the size of the number of instruction groups containing a tuple(0, 100). [[nodiscard]] auto getBounds() const -> std::vector> override { - std::vector> Vec(InstructionGroups.size(), - std::make_tuple(0, 100)); + std::vector> Vec(Instructions.size(), std::make_tuple(0, 100)); return Vec; } diff --git a/include/firestarter/Platform/PlatformConfig.hpp b/include/firestarter/Platform/PlatformConfig.hpp index e990c3ae..19bf5f5a 100644 --- a/include/firestarter/Platform/PlatformConfig.hpp +++ b/include/firestarter/Platform/PlatformConfig.hpp @@ -109,7 +109,7 @@ class PlatformConfig { /// comma-seperated. void selectInstructionGroups(const InstructionGroups& Groups) { const auto& AvailableInstructionGroups = payload()->getAvailableInstructions(); - for (const auto& [Instruction, Value] : Groups.Groups) { + for (const auto& [Instruction, Value] : static_cast(Groups)) { if (std::find(AvailableInstructionGroups.begin(), AvailableInstructionGroups.end(), Instruction) == AvailableInstructionGroups.end()) { throw std::invalid_argument("Invalid instruction-group: " + Instruction + diff --git a/src/firestarter/Config/InstructionGroups.cpp b/src/firestarter/Config/InstructionGroups.cpp index 2abd99e0..e12698cb 100644 --- a/src/firestarter/Config/InstructionGroups.cpp +++ b/src/firestarter/Config/InstructionGroups.cpp @@ -21,6 +21,7 @@ #include "firestarter/Config/InstructionGroups.hpp" +#include #include namespace firestarter { @@ -55,4 +56,28 @@ auto InstructionGroups::fromString(const std::string& Groups) -> InstructionGrou return InstructionGroups{ParsedGroups}; } +auto InstructionGroups::fromInstructionAndValues(const std::vector& Instructions, + const std::vector& Values) -> InstructionGroups { + assert(Instructions.size() == Values.size()); + + std::vector> Groups; + + auto It1 = Instructions.begin(); + auto It2 = Values.begin(); + for (; It1 != Instructions.end(); ++It1, ++It2) { + Groups.emplace_back(*It1, *It2); + } + + return InstructionGroups{Groups}; +} + +auto InstructionGroups::intructions() const -> std::vector { + std::vector Items; + Items.reserve(Groups.size()); + for (auto const& Pair : Groups) { + Items.push_back(Pair.first); + } + return Items; +} + } // namespace firestarter \ No newline at end of file diff --git a/src/firestarter/Payload/PayloadSettings.cpp b/src/firestarter/Payload/PayloadSettings.cpp index 612e62d6..560ce787 100644 --- a/src/firestarter/Payload/PayloadSettings.cpp +++ b/src/firestarter/Payload/PayloadSettings.cpp @@ -41,7 +41,7 @@ auto PayloadSettings::getSequenceStartCount(const std::vector& Sequ } auto PayloadSettings::generateSequence(InstructionGroups const& Proportions) -> std::vector { - std::vector> Prop = Proportions.Groups; + auto Prop = static_cast(Proportions); Prop.erase(std::remove_if(Prop.begin(), Prop.end(), [](auto const& Pair) { return Pair.second == 0; }), Prop.end()); From 303c3774e72f5b5b5662a23ad889a1816c2fb3f7 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Wed, 11 Dec 2024 11:46:17 +0100 Subject: [PATCH 17/31] remove const in class private var --- include/firestarter/X86/X86FunctionSelection.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/firestarter/X86/X86FunctionSelection.hpp b/include/firestarter/X86/X86FunctionSelection.hpp index 3d59982e..fdc5e350 100644 --- a/include/firestarter/X86/X86FunctionSelection.hpp +++ b/include/firestarter/X86/X86FunctionSelection.hpp @@ -57,7 +57,7 @@ class X86FunctionSelection final : public FunctionSelection { /// The list of availabe platform configs that is printed when supplying the --avail command line argument. The IDs /// for these configs are generated by iterating through this list starting with 1. To maintain stable IDs in /// FIRESTARTER new configs should be added to the bottom of the list. - const std::vector> PlatformConfigs = { + std::vector> PlatformConfigs = { std::make_shared(), std::make_shared(), std::make_shared(), std::make_shared(), std::make_shared(), std::make_shared(), @@ -71,7 +71,7 @@ class X86FunctionSelection final : public FunctionSelection { /// therefore it is the last on the list. CPUs that support AVX512 will most certainly also support FMA and AVX, /// AVX512 takes precedence. This list should contain one entry for each of the supported CPU extensions by the /// FIRESTARTER payloads. - const std::vector> FallbackPlatformConfigs = { + std::vector> FallbackPlatformConfigs = { std::make_shared(), // AVX512 std::make_shared(), // FMA4 std::make_shared(), // FMA From b754921b3fc87ebb023f770ee5ee254c9e5c31de Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Wed, 11 Dec 2024 11:53:59 +0100 Subject: [PATCH 18/31] cleanup --- include/firestarter/Firestarter.hpp | 2 +- include/firestarter/LoadWorkerData.hpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/include/firestarter/Firestarter.hpp b/include/firestarter/Firestarter.hpp index d5fd2595..55999538 100644 --- a/include/firestarter/Firestarter.hpp +++ b/include/firestarter/Firestarter.hpp @@ -26,6 +26,7 @@ #include "firestarter/Constants.hpp" #include "firestarter/Cuda/Cuda.hpp" #include "firestarter/DumpRegisterWorkerData.hpp" +#include "firestarter/FunctionSelection.hpp" #include "firestarter/LoadWorkerData.hpp" #include "firestarter/Measurement/MeasurementWorker.hpp" #include "firestarter/OneAPI/OneAPI.hpp" @@ -39,7 +40,6 @@ #include #include #include -#include #include #if defined(linux) || defined(__linux__) diff --git a/include/firestarter/LoadWorkerData.hpp b/include/firestarter/LoadWorkerData.hpp index b5f1d7af..10971ad5 100644 --- a/include/firestarter/LoadWorkerData.hpp +++ b/include/firestarter/LoadWorkerData.hpp @@ -23,7 +23,6 @@ #include "firestarter/CPUTopology.hpp" #include "firestarter/Constants.hpp" -#include "firestarter/FunctionSelection.hpp" #include "firestarter/LoadWorkerMemory.hpp" #include "firestarter/Platform/PlatformConfig.hpp" #include "firestarter/ProcessorInformation.hpp" @@ -170,7 +169,7 @@ class LoadWorkerData { std::shared_ptr ProcessorInfos; /// The reference to the processor topology abstraction which allows setting thread affinity. const CPUTopology& Topology; - /// The config that is cloned for this specific load worker. + /// The config that is cloned from the environment for this specfic load worker. std::unique_ptr Config; }; From 6d4aa75b833f32d3fd87e68e2bb42085cb7dbec9 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Wed, 11 Dec 2024 12:12:53 +0100 Subject: [PATCH 19/31] remove one member from the firestarter class --- include/firestarter/Firestarter.hpp | 3 --- src/firestarter/Firestarter.cpp | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/include/firestarter/Firestarter.hpp b/include/firestarter/Firestarter.hpp index 55999538..2a870413 100644 --- a/include/firestarter/Firestarter.hpp +++ b/include/firestarter/Firestarter.hpp @@ -26,7 +26,6 @@ #include "firestarter/Constants.hpp" #include "firestarter/Cuda/Cuda.hpp" #include "firestarter/DumpRegisterWorkerData.hpp" -#include "firestarter/FunctionSelection.hpp" #include "firestarter/LoadWorkerData.hpp" #include "firestarter/Measurement/MeasurementWorker.hpp" #include "firestarter/OneAPI/OneAPI.hpp" @@ -72,8 +71,6 @@ class Firestarter { CPUTopology Topology; /// This class holds the information about the current processor which is specific to one architecture. std::shared_ptr ProcessorInfos; - /// The class that handles setting up the payload for firestarter - std::unique_ptr FunctionSelectionPtr; /// The selection function. std::unique_ptr FunctionPtr; /// The class for execution of the gemm routine on Cuda or HIP GPUs. diff --git a/src/firestarter/Firestarter.cpp b/src/firestarter/Firestarter.cpp index 0d77ccb0..2cbcda0a 100644 --- a/src/firestarter/Firestarter.cpp +++ b/src/firestarter/Firestarter.cpp @@ -35,6 +35,8 @@ namespace firestarter { Firestarter::Firestarter(Config&& ProvidedConfig) : Cfg(std::move(ProvidedConfig)) { + std::unique_ptr FunctionSelectionPtr; + if constexpr (firestarter::OptionalFeatures.IsX86) { ProcessorInfos = std::make_shared(); FunctionSelectionPtr = std::make_unique(); From 2e407cdb0f6ad9458f116343db6daf04b3e905d3 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Wed, 11 Dec 2024 12:36:13 +0100 Subject: [PATCH 20/31] do not set instruction groups in payload directly --- include/firestarter/Firestarter.hpp | 2 +- include/firestarter/Platform/PlatformConfig.hpp | 2 -- src/firestarter/Firestarter.cpp | 1 + 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/include/firestarter/Firestarter.hpp b/include/firestarter/Firestarter.hpp index 2a870413..7f4a4e53 100644 --- a/include/firestarter/Firestarter.hpp +++ b/include/firestarter/Firestarter.hpp @@ -142,7 +142,7 @@ class Firestarter { for (auto& Thread : LoadThreads) { auto Td = Thread.second; - Td->config().settings().selectInstructionGroups(Setting); + Td->config().selectInstructionGroups(Setting); } signalLoadWorkers(LoadThreadState::ThreadSwitch, SwitchLoad::func); diff --git a/include/firestarter/Platform/PlatformConfig.hpp b/include/firestarter/Platform/PlatformConfig.hpp index 19bf5f5a..7df6b1fb 100644 --- a/include/firestarter/Platform/PlatformConfig.hpp +++ b/include/firestarter/Platform/PlatformConfig.hpp @@ -119,8 +119,6 @@ class PlatformConfig { } settings().selectInstructionGroups(Groups); - - log::info() << " Running custom instruction group: " << Groups; } /// The function name for this platform config given a specific thread per core count. diff --git a/src/firestarter/Firestarter.cpp b/src/firestarter/Firestarter.cpp index 2cbcda0a..49cfbb51 100644 --- a/src/firestarter/Firestarter.cpp +++ b/src/firestarter/Firestarter.cpp @@ -77,6 +77,7 @@ Firestarter::Firestarter(Config&& ProvidedConfig) } if (Cfg.Groups) { FunctionPtr->selectInstructionGroups(*Cfg.Groups); + log::info() << " Running custom instruction group: " << *Cfg.Groups; } if (Cfg.LineCount) { From 6d98bd576ef443cd4bb5b5d6e689d71d06f2753f Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Wed, 11 Dec 2024 12:56:16 +0100 Subject: [PATCH 21/31] cleanup interfaces --- include/firestarter/Firestarter.hpp | 2 +- include/firestarter/LoadWorkerData.hpp | 2 +- .../firestarter/Platform/PlatformConfig.hpp | 30 +++++++++++-------- .../Platform/PlatformConfigAndThreads.hpp | 2 +- .../X86/Platform/X86PlatformConfig.hpp | 3 +- src/firestarter/Firestarter.cpp | 6 ++-- src/firestarter/FunctionSelection.cpp | 4 +-- 7 files changed, 28 insertions(+), 21 deletions(-) diff --git a/include/firestarter/Firestarter.hpp b/include/firestarter/Firestarter.hpp index 7f4a4e53..03335b73 100644 --- a/include/firestarter/Firestarter.hpp +++ b/include/firestarter/Firestarter.hpp @@ -142,7 +142,7 @@ class Firestarter { for (auto& Thread : LoadThreads) { auto Td = Thread.second; - Td->config().selectInstructionGroups(Setting); + Td->Config->selectInstructionGroups(Setting); } signalLoadWorkers(LoadThreadState::ThreadSwitch, SwitchLoad::func); diff --git a/include/firestarter/LoadWorkerData.hpp b/include/firestarter/LoadWorkerData.hpp index 10971ad5..fe7d8049 100644 --- a/include/firestarter/LoadWorkerData.hpp +++ b/include/firestarter/LoadWorkerData.hpp @@ -102,7 +102,7 @@ class LoadWorkerData { /// Gettter for the id of the thread. [[nodiscard]] auto id() const -> uint64_t { return Id; } /// Getter for the current platform config. - [[nodiscard]] auto config() const -> platform::PlatformConfig& { return *Config; } + [[nodiscard]] auto config() const -> const platform::PlatformConfig& { return *Config; } /// Access the DumpRegisterStruct. Asserts when dumping registers is not enabled. /// \returns a reference to the DumpRegisterStruct diff --git a/include/firestarter/Platform/PlatformConfig.hpp b/include/firestarter/Platform/PlatformConfig.hpp index 7df6b1fb..2dfa5f40 100644 --- a/include/firestarter/Platform/PlatformConfig.hpp +++ b/include/firestarter/Platform/PlatformConfig.hpp @@ -46,14 +46,14 @@ class PlatformConfig { std::shared_ptr Payload; public: + /// Getter for const ref to this type + [[nodiscard]] auto constRef() const -> const auto& { return *this; } + /// Getter for the name of the platform. [[nodiscard]] auto name() const -> const auto& { return Name; } /// Getter for the settings of the platform. - [[nodiscard]] auto settings() const -> const auto& { return Settings; } - - /// Reference to the settings. This allows them to be overriden. - [[nodiscard]] auto settings() -> auto& { return Settings; } + [[nodiscard]] auto settings() const -> const payload::PayloadSettings& { return Settings; } /// Getter for the payload of the platform. [[nodiscard]] auto payload() const -> const auto& { return Payload; } @@ -70,6 +70,9 @@ class PlatformConfig { [[nodiscard]] auto isDefault(const ProcessorInformation& Topology) const -> bool { return isDefault(&Topology); } protected: + /// Non const Getter for the settings of the platform. + [[nodiscard]] auto settings() -> payload::PayloadSettings& { return Settings; } + /// Check if this platform is available on the current system. This transloate to if the cpu extensions are /// available for the payload that is used. /// \arg Topology The pointer to the CPUTopology that is used to check agains if this platform is supported. @@ -121,6 +124,9 @@ class PlatformConfig { settings().selectInstructionGroups(Groups); } + /// Save the line count in the payload settings. + void setLineCount(unsigned LineCount) { settings().setLineCount(LineCount); } + /// The function name for this platform config given a specific thread per core count. /// \arg ThreadsPerCore The number of threads per core. /// \returns The name of the function (a platform name, payload name and a specific thread per core count) @@ -130,30 +136,30 @@ class PlatformConfig { /// Get the concreate functions name. [[nodiscard]] auto functionName() const -> std::string { - assert(Settings.isConcreate() && "Settings must be concreate for a concreate function name"); - return functionName(Settings.thread()); + assert(settings().isConcreate() && "Settings must be concreate for a concreate function name"); + return functionName(settings().thread()); }; /// Print a summary for the selected platform/payload with given settings. void printCodePathSummary() const { - assert(Settings.isConcreate() && "Setting must be concreate to print the code path summary."); + assert(settings().isConcreate() && "Setting must be concreate to print the code path summary."); log::info() << "\n" - << " Taking " << Payload->name() << " path optimized for " << Name << " - " << Settings.thread() + << " Taking " << Payload->name() << " path optimized for " << Name << " - " << settings().thread() << " thread(s) per core\n" << " Used buffersizes per thread:"; - if (Settings.instructionCacheSizePerThread()) { - log::info() << " - L1i-Cache: " << *Settings.instructionCacheSizePerThread() << " Bytes"; + if (settings().instructionCacheSizePerThread()) { + log::info() << " - L1i-Cache: " << *settings().instructionCacheSizePerThread() << " Bytes"; } unsigned I = 1; - for (auto const& Bytes : Settings.dataCacheBufferSizePerThread()) { + for (auto const& Bytes : settings().dataCacheBufferSizePerThread()) { log::info() << " - L" << I << "d-Cache: " << Bytes << " Bytes"; I++; } - log::info() << " - Memory: " << Settings.ramBufferSizePerThread() << " Bytes"; + log::info() << " - Memory: " << settings().ramBufferSizePerThread() << " Bytes"; } }; diff --git a/include/firestarter/Platform/PlatformConfigAndThreads.hpp b/include/firestarter/Platform/PlatformConfigAndThreads.hpp index 8a9bc179..d650779e 100644 --- a/include/firestarter/Platform/PlatformConfigAndThreads.hpp +++ b/include/firestarter/Platform/PlatformConfigAndThreads.hpp @@ -42,7 +42,7 @@ struct PlatformConfigAndThreads { -> std::vector { std::vector Vec; - for (const auto& Thread : Config->settings().threads()) { + for (const auto& Thread : Config->constRef().settings().threads()) { Vec.emplace_back(PlatformConfigAndThreads{Config, Thread}); } diff --git a/include/firestarter/X86/Platform/X86PlatformConfig.hpp b/include/firestarter/X86/Platform/X86PlatformConfig.hpp index b41faf5d..1aa4169d 100644 --- a/include/firestarter/X86/Platform/X86PlatformConfig.hpp +++ b/include/firestarter/X86/Platform/X86PlatformConfig.hpp @@ -70,7 +70,8 @@ class X86PlatformConfig : public firestarter::platform::PlatformConfig { [[nodiscard]] auto cloneConcreate(std::optional InstructionCacheSize, unsigned ThreadsPerCore) const -> std::unique_ptr final { auto Ptr = clone(); - Ptr->settings().concretize(InstructionCacheSize, ThreadsPerCore); + auto* DerivedPtr = dynamic_cast(Ptr.get()); + DerivedPtr->settings().concretize(InstructionCacheSize, ThreadsPerCore); return Ptr; } diff --git a/src/firestarter/Firestarter.cpp b/src/firestarter/Firestarter.cpp index 49cfbb51..4eeaf6da 100644 --- a/src/firestarter/Firestarter.cpp +++ b/src/firestarter/Firestarter.cpp @@ -81,7 +81,7 @@ Firestarter::Firestarter(Config&& ProvidedConfig) } if (Cfg.LineCount) { - FunctionPtr->settings().setLineCount(*Cfg.LineCount); + FunctionPtr->setLineCount(*Cfg.LineCount); } if constexpr (firestarter::OptionalFeatures.OptimizationEnabled) { @@ -156,7 +156,7 @@ Firestarter::Firestarter(Config&& ProvidedConfig) auto Prob = std::make_shared( std::move(ApplySettings), MeasurementWorker, Cfg.OptimizationMetrics, Cfg.EvaluationDuration, Cfg.StartDelta, - Cfg.StopDelta, FunctionPtr->settings().groups().intructions()); + Cfg.StopDelta, FunctionPtr->constRef().settings().groups().intructions()); Population = std::make_unique(std::move(Prob)); @@ -227,7 +227,7 @@ void Firestarter::mainThread() { Firestarter::Optimizer->join(); Firestarter::Optimizer.reset(); - auto PayloadItems = FunctionPtr->settings().groups().intructions(); + const auto PayloadItems = FunctionPtr->constRef().settings().groups().intructions(); firestarter::optimizer::History::save(Cfg.OptimizeOutfile, StartTime, PayloadItems, Cfg.Argc, Cfg.Argv); diff --git a/src/firestarter/FunctionSelection.cpp b/src/firestarter/FunctionSelection.cpp index 14a8d735..b4867bd9 100644 --- a/src/firestarter/FunctionSelection.cpp +++ b/src/firestarter/FunctionSelection.cpp @@ -95,7 +95,7 @@ auto FunctionSelection::selectDefaultOrFallbackFunction(const ProcessorInformati // find the fallback implementation with the correct thread per core count or select the first available thread // per core count { - const auto& Threads = FallbackPlatformConfigPtr->settings().threads(); + const auto& Threads = FallbackPlatformConfigPtr->constRef().settings().threads(); const auto& ThreadIt = std::find(Threads.cbegin(), Threads.cend(), ProcessorThreadsPerCore); if (ThreadIt == Threads.cend()) { SelectedThreadsPerCore = Threads.front(); @@ -140,7 +140,7 @@ void FunctionSelection::printFunctionSummary(const ProcessorInformation& Process for (const auto& Platform : platform::PlatformConfigAndThreads::fromPlatformConfigs(platformConfigs())) { const char* Available = (Platform.Config->isAvailable(ProcessorInfos) || ForceYes) ? "yes" : "no"; const auto& FunctionName = Platform.Config->functionName(Platform.ThreadCount); - const auto& InstructionGroupsString = Platform.Config->settings().groups(); + const auto& InstructionGroupsString = Platform.Config->constRef().settings().groups(); log::info() << " " << std::right << std::setw(4) << Id << " | " << std::left << std::setw(30) << FunctionName << " | " << std::left << std::setw(24) << Available << " | " << InstructionGroupsString; From 769df8bfe12a6a48d0aa3c5d7f3939fc6be17662 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Wed, 11 Dec 2024 17:03:34 +0100 Subject: [PATCH 22/31] remove unused header --- include/firestarter/CPUTopology.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/firestarter/CPUTopology.hpp b/include/firestarter/CPUTopology.hpp index b129d96a..d4919932 100644 --- a/include/firestarter/CPUTopology.hpp +++ b/include/firestarter/CPUTopology.hpp @@ -22,7 +22,6 @@ #pragma once #include -#include #include extern "C" { From 8decd44afdc2dc9abd79c62b1af85e73c1b9ddc2 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Wed, 11 Dec 2024 17:04:09 +0100 Subject: [PATCH 23/31] clang-tidy suggestions --- include/firestarter/LoadWorkerData.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/firestarter/LoadWorkerData.hpp b/include/firestarter/LoadWorkerData.hpp index fe7d8049..e3153f54 100644 --- a/include/firestarter/LoadWorkerData.hpp +++ b/include/firestarter/LoadWorkerData.hpp @@ -73,7 +73,7 @@ class LoadWorkerData { /// compiled payload. /// \arg ErrorDetection Should the code to support error detection between thread be baked into the high load routine /// of the compiled payload. - LoadWorkerData(uint64_t Id, uint64_t OsIndex, const std::shared_ptr& ProcessorInfos, + LoadWorkerData(uint64_t Id, uint64_t OsIndex, std::shared_ptr ProcessorInfos, const std::unique_ptr& FunctionPtr, const CPUTopology& Topology, volatile LoadThreadWorkType& LoadVar, std::chrono::microseconds Period, bool DumpRegisters, bool ErrorDetection) @@ -83,7 +83,7 @@ class LoadWorkerData { , ErrorDetection(ErrorDetection) , Id(Id) , OsIndex(OsIndex) - , ProcessorInfos(ProcessorInfos) + , ProcessorInfos(std::move(ProcessorInfos)) , Topology(Topology) , Config(FunctionPtr->clone()) {} From c3dc155f50e2f9b2f51fc0d2ebca90aeb34210cc Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Wed, 11 Dec 2024 17:26:57 +0100 Subject: [PATCH 24/31] unit test InstructionGroups parsing --- test/UnitTests/CMakeLists.txt | 1 + test/UnitTests/InstructionGroupsTest.cpp | 86 ++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 test/UnitTests/InstructionGroupsTest.cpp diff --git a/test/UnitTests/CMakeLists.txt b/test/UnitTests/CMakeLists.txt index fd23745d..c4b35248 100644 --- a/test/UnitTests/CMakeLists.txt +++ b/test/UnitTests/CMakeLists.txt @@ -1,5 +1,6 @@ add_executable(UnitTests CpuBindTest.cpp + InstructionGroupsTest.cpp ) target_link_libraries(UnitTests diff --git a/test/UnitTests/InstructionGroupsTest.cpp b/test/UnitTests/InstructionGroupsTest.cpp new file mode 100644 index 00000000..2e565644 --- /dev/null +++ b/test/UnitTests/InstructionGroupsTest.cpp @@ -0,0 +1,86 @@ +/****************************************************************************** + * FIRESTARTER - A Processor Stress Test Utility + * Copyright (C) 2024 TU Dresden, Center for Information Services and High + * Performance Computing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Contact: daniel.hackenberg@tu-dresden.de + *****************************************************************************/ + +#include "firestarter/Config/InstructionGroups.hpp" + +#include + +TEST(InstructionGroupsTest, ParseValidInput) { + const auto StringToParsed = std::map>>({ + {"Inst:1", {{"Inst", 1}}}, + {"Inst_2:2", {{"Inst_2", 2}}}, + }); + + // Check if the individual ones work. + for (const auto& [Input, Output] : StringToParsed) { + const auto Groups = firestarter::InstructionGroups::fromString(Input); + const auto ConvertedGroups = static_cast>>(Groups); + EXPECT_EQ(ConvertedGroups, Output); + + { + std::stringstream Ss; + Ss << Groups; + EXPECT_EQ(Ss.str(), Input); + } + } + + // Check combinations with two comma seperated values. + for (const auto& [Input1, Output1] : StringToParsed) { + for (const auto& [Input2, Output2] : StringToParsed) { + auto Input = Input1; + Input += ","; + Input += Input2; + + auto Output = Output1; + Output.insert(Output.end(), Output2.cbegin(), Output2.cend()); + + const auto Groups = firestarter::InstructionGroups::fromString(Input); + const auto ConvertedGroups = static_cast>>(Groups); + EXPECT_EQ(ConvertedGroups, Output); + + { + std::stringstream Ss; + Ss << Groups; + EXPECT_EQ(Ss.str(), Input); + } + } + } +} + +TEST(InstructionGroupsTest, ParseInvalidInput) { + const auto ThrowStrings = std::vector({"Inst", "$:1", "Inst:0", "Inst:-1", "Inst:$", "Inst:A"}); + + // Check if the individual ones fail. + for (const auto& Input : ThrowStrings) { + EXPECT_ANY_THROW((void)firestarter::InstructionGroups::fromString(Input)); + } + + // Check if the combinations with two comma seperated values fail. + for (const auto& Input1 : ThrowStrings) { + for (const auto& Input2 : ThrowStrings) { + auto Input = Input1; + Input += ","; + Input += Input2; + + EXPECT_ANY_THROW((void)firestarter::InstructionGroups::fromString(Input)); + } + } +} \ No newline at end of file From 2b7e2c857b95daae8b9b202ca83d9f6cfa4cb6a0 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Wed, 11 Dec 2024 17:35:45 +0100 Subject: [PATCH 25/31] add newline in file --- include/firestarter/Payload/PayloadSettings.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/firestarter/Payload/PayloadSettings.hpp b/include/firestarter/Payload/PayloadSettings.hpp index c1e50807..73827427 100644 --- a/include/firestarter/Payload/PayloadSettings.hpp +++ b/include/firestarter/Payload/PayloadSettings.hpp @@ -22,6 +22,7 @@ #pragma once #include "firestarter/Config/InstructionGroups.hpp" + #include #include #include From d6b84aafb3aa16135f8a8a9b62caf3375ecbe840 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Fri, 13 Dec 2024 00:11:17 +0100 Subject: [PATCH 26/31] remove unneeded functions --- .../firestarter/Platform/PlatformConfig.hpp | 14 ----------- .../X86/Platform/X86PlatformConfig.hpp | 24 ++----------------- src/firestarter/FunctionSelection.cpp | 6 ++--- 3 files changed, 5 insertions(+), 39 deletions(-) diff --git a/include/firestarter/Platform/PlatformConfig.hpp b/include/firestarter/Platform/PlatformConfig.hpp index 2dfa5f40..3eda4783 100644 --- a/include/firestarter/Platform/PlatformConfig.hpp +++ b/include/firestarter/Platform/PlatformConfig.hpp @@ -58,12 +58,6 @@ class PlatformConfig { /// Getter for the payload of the platform. [[nodiscard]] auto payload() const -> const auto& { return Payload; } - /// Check if this platform is available on the current system. This transloate to if the cpu extensions are - /// available for the payload that is used. - /// \arg Topology The reference to the CPUTopology that is used to check agains if this platform is supported. - /// \returns true if the platform is supported on the given CPUTopology. - [[nodiscard]] auto isAvailable(const ProcessorInformation& Topology) const -> bool { return isAvailable(&Topology); } - /// Check if this platform is available and the default on the current system. /// \arg Topology The reference to the CPUTopology that is used to check agains if this payload is supported. /// \returns true if the platform is the default one for a given CPUTopology. @@ -73,14 +67,6 @@ class PlatformConfig { /// Non const Getter for the settings of the platform. [[nodiscard]] auto settings() -> payload::PayloadSettings& { return Settings; } - /// Check if this platform is available on the current system. This transloate to if the cpu extensions are - /// available for the payload that is used. - /// \arg Topology The pointer to the CPUTopology that is used to check agains if this platform is supported. - /// \returns true if the platform is supported on the given CPUTopology. - [[nodiscard]] virtual auto isAvailable(const ProcessorInformation* Topology) const -> bool { - return payload()->isAvailable(*Topology); - } - /// Check if this platform is available and the default on the current system. /// \arg Topology The pointer to the CPUTopology that is used to check agains if this payload is supported. /// \returns true if the platform is the default one for a given CPUTopology. diff --git a/include/firestarter/X86/Platform/X86PlatformConfig.hpp b/include/firestarter/X86/Platform/X86PlatformConfig.hpp index 1aa4169d..a81cb711 100644 --- a/include/firestarter/X86/Platform/X86PlatformConfig.hpp +++ b/include/firestarter/X86/Platform/X86PlatformConfig.hpp @@ -43,19 +43,6 @@ class X86PlatformConfig : public firestarter::platform::PlatformConfig { , Family(Family) , Models(std::move(Models)) {} - /// Check if this platform is available on the current system. This transloate to if the cpu extensions are - /// available for the payload that is used. - /// \arg Topology The reference to the X86CPUTopology that is used to check agains if this platform is supported. - /// \returns true if the platform is supported on the given X86CPUTopology. - [[nodiscard]] auto isAvailable(const X86ProcessorInformation& Topology) const -> bool { - return isAvailable(&Topology); - } - - /// Check if this platform is available and the default on the current system. - /// \arg Topology The reference to the X86CPUTopology that is used to check agains if this payload is supported. - /// \returns true if the platform is the default one for a given X86CPUTopology. - [[nodiscard]] auto isDefault(const X86ProcessorInformation& Topology) const -> bool { return isDefault(&Topology); } - /// Clone a the platform config. [[nodiscard]] auto clone() const -> std::unique_ptr final { auto Ptr = std::make_unique(name(), Family, std::list(Models), @@ -76,14 +63,6 @@ class X86PlatformConfig : public firestarter::platform::PlatformConfig { } private: - /// Check if this platform is available on the current system. This tranlates to if the cpu extensions are - /// available for the payload that is used. - /// \arg Topology The pointer to the CPUTopology that is used to check agains if this platform is supported. - /// \returns true if the platform is supported on the given CPUTopology. - [[nodiscard]] auto isAvailable(const ProcessorInformation* Topology) const -> bool final { - return firestarter::platform::PlatformConfig::isAvailable(Topology); - } - /// Check if this platform is available and the default on the current system. This is done by checking if the family /// id in the CPUTopology matches the one saved in Family and if the model id in the CPUTopology is contained in /// Models. @@ -96,7 +75,8 @@ class X86PlatformConfig : public firestarter::platform::PlatformConfig { // Check if the family of the topology matches the family of the config, if the model of the topology is contained // in the models list of the config and if the config is available on the current platform. return Family == FinalTopology->familyId() && - (std::find(Models.begin(), Models.end(), FinalTopology->modelId()) != Models.end()) && isAvailable(Topology); + (std::find(Models.begin(), Models.end(), FinalTopology->modelId()) != Models.end()) && + payload()->isAvailable(*Topology); } }; diff --git a/src/firestarter/FunctionSelection.cpp b/src/firestarter/FunctionSelection.cpp index b4867bd9..b4164559 100644 --- a/src/firestarter/FunctionSelection.cpp +++ b/src/firestarter/FunctionSelection.cpp @@ -39,7 +39,7 @@ auto FunctionSelection::selectAvailableFunction(unsigned FunctionId, const Proce for (const auto& Platform : platform::PlatformConfigAndThreads::fromPlatformConfigs(platformConfigs())) { // the selected function if (Id == FunctionId) { - if (!Platform.Config->isAvailable(ProcessorInfos)) { + if (!Platform.Config->payload()->isAvailable(ProcessorInfos)) { const auto ErrorString = "Function " + std::to_string(FunctionId) + " (\"" + Platform.Config->functionName(Platform.ThreadCount) + "\") requires " + Platform.Config->payload()->name() + ", which is not supported by the processor."; @@ -89,7 +89,7 @@ auto FunctionSelection::selectDefaultOrFallbackFunction(const ProcessorInformati // loop over available implementation and check if they are marked as // fallback for (const auto& FallbackPlatformConfigPtr : fallbackPlatformConfigs()) { - if (FallbackPlatformConfigPtr->isAvailable(ProcessorInfos)) { + if (FallbackPlatformConfigPtr->payload()->isAvailable(ProcessorInfos)) { unsigned SelectedThreadsPerCore{}; // find the fallback implementation with the correct thread per core count or select the first available thread @@ -138,7 +138,7 @@ void FunctionSelection::printFunctionSummary(const ProcessorInformation& Process auto Id = 1U; for (const auto& Platform : platform::PlatformConfigAndThreads::fromPlatformConfigs(platformConfigs())) { - const char* Available = (Platform.Config->isAvailable(ProcessorInfos) || ForceYes) ? "yes" : "no"; + const char* Available = (Platform.Config->payload()->isAvailable(ProcessorInfos) || ForceYes) ? "yes" : "no"; const auto& FunctionName = Platform.Config->functionName(Platform.ThreadCount); const auto& InstructionGroupsString = Platform.Config->constRef().settings().groups(); From 09797a6d8411d7c8df131dc6b12556fd2d6a13fc Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Fri, 13 Dec 2024 23:10:23 +0100 Subject: [PATCH 27/31] wrapp asmjit cpufeatures to refactor payload isAvailable function --- include/firestarter/CpuFeatures.hpp | 38 ++++++++++ include/firestarter/Payload/Payload.hpp | 8 +-- include/firestarter/ProcessorInformation.hpp | 10 ++- .../firestarter/X86/Payload/AVX512Payload.hpp | 42 +++++------ .../firestarter/X86/Payload/AVXPayload.hpp | 40 ++++++----- .../firestarter/X86/Payload/FMA4Payload.hpp | 4 +- .../firestarter/X86/Payload/FMAPayload.hpp | 21 +++--- .../firestarter/X86/Payload/SSE2Payload.hpp | 40 ++++++----- .../firestarter/X86/Payload/X86Payload.hpp | 35 ++++----- .../firestarter/X86/Payload/ZENFMAPayload.hpp | 5 +- .../X86/Platform/X86PlatformConfig.hpp | 2 +- include/firestarter/X86/X86CpuFeatures.hpp | 63 ++++++++++++++++ src/firestarter/FunctionSelection.cpp | 7 +- src/firestarter/ProcessorInformation.cpp | 6 +- .../X86/X86ProcessorInformation.cpp | 3 +- test/UnitTests/CMakeLists.txt | 2 + test/UnitTests/X86CpuFeaturesTest.cpp | 46 ++++++++++++ test/UnitTests/X86PayloadTest.cpp | 72 +++++++++++++++++++ 18 files changed, 341 insertions(+), 103 deletions(-) create mode 100644 include/firestarter/CpuFeatures.hpp create mode 100644 include/firestarter/X86/X86CpuFeatures.hpp create mode 100644 test/UnitTests/X86CpuFeaturesTest.cpp create mode 100644 test/UnitTests/X86PayloadTest.cpp diff --git a/include/firestarter/CpuFeatures.hpp b/include/firestarter/CpuFeatures.hpp new file mode 100644 index 00000000..57b49917 --- /dev/null +++ b/include/firestarter/CpuFeatures.hpp @@ -0,0 +1,38 @@ +/****************************************************************************** + * FIRESTARTER - A Processor Stress Test Utility + * Copyright (C) 2024 TU Dresden, Center for Information Services and High + * Performance Computing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Contact: daniel.hackenberg@tu-dresden.de + *****************************************************************************/ + +#pragma once + +namespace firestarter { + +/// Abstract class that defines the methods required to check if cpu features are available. +class CpuFeatures { +public: + CpuFeatures() = default; + virtual ~CpuFeatures() = default; + + /// Check if this class has all features which are given in the argument. + /// \arg Features The features which should be check if they are available. + /// \returns true if this class has all features given in the argument. + [[nodiscard]] virtual auto hasAll(const CpuFeatures& Features) const -> bool = 0; +}; + +} // namespace firestarter diff --git a/include/firestarter/Payload/Payload.hpp b/include/firestarter/Payload/Payload.hpp index 97813d76..7b2819b9 100644 --- a/include/firestarter/Payload/Payload.hpp +++ b/include/firestarter/Payload/Payload.hpp @@ -22,10 +22,10 @@ #pragma once #include "firestarter/Constants.hpp" +#include "firestarter/CpuFeatures.hpp" #include "firestarter/Logging/Log.hpp" #include "firestarter/Payload/CompiledPayload.hpp" #include "firestarter/Payload/PayloadSettings.hpp" -#include "firestarter/ProcessorInformation.hpp" #include #include @@ -85,9 +85,9 @@ class Payload { /// Check if this payload is available on the current system. This usally translates if the cpu extensions are /// available. - /// \arg Topology The CPUTopology that is used to check agains if this payload is supported. - /// \returns true if the payload is supported on the given CPUTopology. - [[nodiscard]] virtual auto isAvailable(const ProcessorInformation& Topology) const -> bool = 0; + /// \arg CpuFeatures Features that this payload requires to check agains if this payload is supported. + /// \returns true if the payload is supported on the system with the given features. + [[nodiscard]] virtual auto isAvailable(const CpuFeatures& Features) const -> bool = 0; /// Compile this payload with supplied settings and optional features. /// \arg Settings The settings for this payload e.g., the number of lines or the size of the caches. diff --git a/include/firestarter/ProcessorInformation.hpp b/include/firestarter/ProcessorInformation.hpp index d5e2173e..2eeaa097 100644 --- a/include/firestarter/ProcessorInformation.hpp +++ b/include/firestarter/ProcessorInformation.hpp @@ -21,8 +21,11 @@ #pragma once +#include "firestarter/CpuFeatures.hpp" + #include #include +#include #include #include @@ -35,7 +38,7 @@ namespace firestarter { /// This class models the properties of a processor. class ProcessorInformation { public: - explicit ProcessorInformation(std::string Architecture); + explicit ProcessorInformation(std::string Architecture, std::unique_ptr&& Features); virtual ~ProcessorInformation() = default; /// Getter for the clockrate in Hz @@ -50,6 +53,9 @@ class ProcessorInformation { /// The model of the processor. With X86 this is the the string of Family, Model and Stepping. [[nodiscard]] virtual auto model() const -> std::string const& = 0; + /// Getter for the cpu features abstraction + [[nodiscard]] auto cpuFeatures() const -> const CpuFeatures& { return *Features; } + /// Print the information about this process to a stream. void print() const; @@ -67,6 +73,8 @@ class ProcessorInformation { private: /// The CPU vendor i.e., Intel or AMD. std::string Vendor; + /// The cpu features of this processor. + std::unique_ptr Features; /// Helper function to open a filepath and return a stringstream with its contents. /// \arg FilePath The file to open diff --git a/include/firestarter/X86/Payload/AVX512Payload.hpp b/include/firestarter/X86/Payload/AVX512Payload.hpp index 6bc42b79..8c102401 100644 --- a/include/firestarter/X86/Payload/AVX512Payload.hpp +++ b/include/firestarter/X86/Payload/AVX512Payload.hpp @@ -29,26 +29,28 @@ namespace firestarter::x86::payload { class AVX512Payload final : public X86Payload { public: AVX512Payload() noexcept - : X86Payload(/*FeatureRequests=*/{asmjit::CpuFeatures::X86::kAVX512_F}, /*Name=*/"AVX512", /*RegisterSize=*/8, - /*RegisterCount=*/32, - /*InstructionFlops=*/ - {{"REG", 32}, - {"L1_L", 32}, - {"L1_BROADCAST", 16}, - {"L1_S", 16}, - {"L1_LS", 16}, - {"L2_L", 32}, - {"L2_S", 16}, - {"L2_LS", 16}, - {"L3_L", 32}, - {"L3_S", 16}, - {"L3_LS", 16}, - {"L3_P", 16}, - {"RAM_L", 32}, - {"RAM_S", 16}, - {"RAM_LS", 16}, - {"RAM_P", 16}}, - /*InstructionMemory=*/{{"RAM_L", 64}, {"RAM_S", 128}, {"RAM_LS", 128}, {"RAM_P", 64}}) {} + : X86Payload( + /*FeatureRequests=*/X86CpuFeatures().add(asmjit::CpuFeatures::X86::Id::kAVX512_F), + /*Name=*/"AVX512", /*RegisterSize=*/8, + /*RegisterCount=*/32, + /*InstructionFlops=*/ + {{"REG", 32}, + {"L1_L", 32}, + {"L1_BROADCAST", 16}, + {"L1_S", 16}, + {"L1_LS", 16}, + {"L2_L", 32}, + {"L2_S", 16}, + {"L2_LS", 16}, + {"L3_L", 32}, + {"L3_S", 16}, + {"L3_LS", 16}, + {"L3_P", 16}, + {"RAM_L", 32}, + {"RAM_S", 16}, + {"RAM_LS", 16}, + {"RAM_P", 16}}, + /*InstructionMemory=*/{{"RAM_L", 64}, {"RAM_S", 128}, {"RAM_LS", 128}, {"RAM_P", 64}}) {} /// Compile this payload with supplied settings and optional features. /// \arg Settings The settings for this payload e.g., the number of lines or the size of the caches. diff --git a/include/firestarter/X86/Payload/AVXPayload.hpp b/include/firestarter/X86/Payload/AVXPayload.hpp index db981ba8..e7066f3a 100644 --- a/include/firestarter/X86/Payload/AVXPayload.hpp +++ b/include/firestarter/X86/Payload/AVXPayload.hpp @@ -29,25 +29,27 @@ namespace firestarter::x86::payload { class AVXPayload final : public X86Payload { public: AVXPayload() - : X86Payload(/*FeatureRequests=*/{asmjit::CpuFeatures::X86::kAVX}, /*Name=*/"AVX", /*RegisterSize=*/4, - /*RegisterCount=*/16, - /*InstructionFlops=*/ - {{"REG", 4}, - {"L1_L", 4}, - {"L1_S", 4}, - {"L1_LS", 4}, - {"L2_L", 4}, - {"L2_S", 4}, - {"L2_LS", 4}, - {"L3_L", 4}, - {"L3_S", 4}, - {"L3_LS", 4}, - {"L3_P", 4}, - {"RAM_L", 4}, - {"RAM_S", 4}, - {"RAM_LS", 4}, - {"RAM_P", 4}}, - /*InstructionMemory=*/{{"RAM_L", 64}, {"RAM_S", 128}, {"RAM_LS", 128}, {"RAM_P", 64}}) {} + : X86Payload( + /*FeatureRequests=*/X86CpuFeatures().add(asmjit::CpuFeatures::X86::Id::kAVX), + /*Name=*/"AVX", /*RegisterSize=*/4, + /*RegisterCount=*/16, + /*InstructionFlops=*/ + {{"REG", 4}, + {"L1_L", 4}, + {"L1_S", 4}, + {"L1_LS", 4}, + {"L2_L", 4}, + {"L2_S", 4}, + {"L2_LS", 4}, + {"L3_L", 4}, + {"L3_S", 4}, + {"L3_LS", 4}, + {"L3_P", 4}, + {"RAM_L", 4}, + {"RAM_S", 4}, + {"RAM_LS", 4}, + {"RAM_P", 4}}, + /*InstructionMemory=*/{{"RAM_L", 64}, {"RAM_S", 128}, {"RAM_LS", 128}, {"RAM_P", 64}}) {} /// Compile this payload with supplied settings and optional features. /// \arg Settings The settings for this payload e.g., the number of lines or the size of the caches. diff --git a/include/firestarter/X86/Payload/FMA4Payload.hpp b/include/firestarter/X86/Payload/FMA4Payload.hpp index 9851c28f..35629b3b 100644 --- a/include/firestarter/X86/Payload/FMA4Payload.hpp +++ b/include/firestarter/X86/Payload/FMA4Payload.hpp @@ -29,7 +29,9 @@ namespace firestarter::x86::payload { class FMA4Payload final : public X86Payload { public: FMA4Payload() noexcept - : X86Payload(/*FeatureRequests=*/{asmjit::CpuFeatures::X86::kAVX, asmjit::CpuFeatures::X86::kFMA4}, + : X86Payload(/*FeatureRequests=*/X86CpuFeatures() + .add(asmjit::CpuFeatures::X86::Id::kAVX) + .add(asmjit::CpuFeatures::X86::Id::kFMA4), /*Name=*/"FMA4", /*RegisterSize=*/4, /*RegisterCount=*/16, /*InstructionFlops=*/ {{"REG", 8}, diff --git a/include/firestarter/X86/Payload/FMAPayload.hpp b/include/firestarter/X86/Payload/FMAPayload.hpp index 82c178b8..dbb11c0c 100644 --- a/include/firestarter/X86/Payload/FMAPayload.hpp +++ b/include/firestarter/X86/Payload/FMAPayload.hpp @@ -29,15 +29,18 @@ namespace firestarter::x86::payload { class FMAPayload final : public X86Payload { public: FMAPayload() noexcept - : X86Payload(/*FeatureRequests=*/{asmjit::CpuFeatures::X86::kAVX, asmjit::CpuFeatures::X86::kFMA}, /*Name=*/"FMA", - /*RegisterSize=*/4, /*RegisterCount=*/16, - /*InstructionFlops=*/{{"REG", 16}, {"L1_L", 16}, {"L1_2L", 16}, {"L1_S", 8}, - {"L1_LS", 8}, {"L1_LS_256", 8}, {"L1_2LS_256", 16}, {"L2_L", 16}, - {"L2_S", 8}, {"L2_LS", 8}, {"L2_LS_256", 8}, {"L2_2LS_256", 16}, - {"L3_L", 16}, {"L3_S", 8}, {"L3_LS", 8}, {"L3_LS_256", 8}, - {"L3_P", 8}, {"RAM_L", 16}, {"RAM_S", 8}, {"RAM_LS", 8}, - {"RAM_P", 8}}, - /*InstructionMemory=*/{{"RAM_L", 64}, {"RAM_S", 128}, {"RAM_LS", 128}, {"RAM_P", 64}}) {} + : X86Payload( + /*FeatureRequests=*/X86CpuFeatures() + .add(asmjit::CpuFeatures::X86::Id::kAVX) + .add(asmjit::CpuFeatures::X86::Id::kFMA), + /*Name=*/"FMA", + /*RegisterSize=*/4, /*RegisterCount=*/16, + /*InstructionFlops=*/{{"REG", 16}, {"L1_L", 16}, {"L1_2L", 16}, {"L1_S", 8}, {"L1_LS", 8}, + {"L1_LS_256", 8}, {"L1_2LS_256", 16}, {"L2_L", 16}, {"L2_S", 8}, {"L2_LS", 8}, + {"L2_LS_256", 8}, {"L2_2LS_256", 16}, {"L3_L", 16}, {"L3_S", 8}, {"L3_LS", 8}, + {"L3_LS_256", 8}, {"L3_P", 8}, {"RAM_L", 16}, {"RAM_S", 8}, {"RAM_LS", 8}, + {"RAM_P", 8}}, + /*InstructionMemory=*/{{"RAM_L", 64}, {"RAM_S", 128}, {"RAM_LS", 128}, {"RAM_P", 64}}) {} /// Compile this payload with supplied settings and optional features. /// \arg Settings The settings for this payload e.g., the number of lines or the size of the caches. diff --git a/include/firestarter/X86/Payload/SSE2Payload.hpp b/include/firestarter/X86/Payload/SSE2Payload.hpp index c685dbbd..cf0ae57c 100644 --- a/include/firestarter/X86/Payload/SSE2Payload.hpp +++ b/include/firestarter/X86/Payload/SSE2Payload.hpp @@ -29,25 +29,27 @@ namespace firestarter::x86::payload { class SSE2Payload final : public X86Payload { public: SSE2Payload() noexcept - : X86Payload(/*FeatureRequests=*/{asmjit::CpuFeatures::X86::kSSE2}, /*Name=*/"SSE2", /*RegisterSize=*/2, - /*RegisterCount=*/16, - /*InstructionFlops=*/ - {{"REG", 2}, - {"L1_L", 2}, - {"L1_S", 2}, - {"L1_LS", 2}, - {"L2_L", 2}, - {"L2_S", 2}, - {"L2_LS", 2}, - {"L3_L", 2}, - {"L3_S", 2}, - {"L3_LS", 2}, - {"L3_P", 2}, - {"RAM_L", 2}, - {"RAM_S", 2}, - {"RAM_LS", 2}, - {"RAM_P", 2}}, - /*InstructionMemory=*/{{"RAM_L", 64}, {"RAM_S", 128}, {"RAM_LS", 128}, {"RAM_P", 64}}) {} + : X86Payload( + /*FeatureRequests=*/X86CpuFeatures().add(asmjit::CpuFeatures::X86::Id::kSSE2), + /*Name=*/"SSE2", /*RegisterSize=*/2, + /*RegisterCount=*/16, + /*InstructionFlops=*/ + {{"REG", 2}, + {"L1_L", 2}, + {"L1_S", 2}, + {"L1_LS", 2}, + {"L2_L", 2}, + {"L2_S", 2}, + {"L2_LS", 2}, + {"L3_L", 2}, + {"L3_S", 2}, + {"L3_LS", 2}, + {"L3_P", 2}, + {"RAM_L", 2}, + {"RAM_S", 2}, + {"RAM_LS", 2}, + {"RAM_P", 2}}, + /*InstructionMemory=*/{{"RAM_L", 64}, {"RAM_S", 128}, {"RAM_LS", 128}, {"RAM_P", 64}}) {} /// Compile this payload with supplied settings and optional features. /// \arg Settings The settings for this payload e.g., the number of lines or the size of the caches. diff --git a/include/firestarter/X86/Payload/X86Payload.hpp b/include/firestarter/X86/Payload/X86Payload.hpp index 18160ba5..fd123731 100644 --- a/include/firestarter/X86/Payload/X86Payload.hpp +++ b/include/firestarter/X86/Payload/X86Payload.hpp @@ -26,7 +26,7 @@ #include "firestarter/LoadWorkerMemory.hpp" #include "firestarter/Logging/Log.hpp" // IWYU pragma: keep #include "firestarter/Payload/Payload.hpp" -#include "firestarter/X86/X86ProcessorInformation.hpp" +#include "firestarter/X86/X86CpuFeatures.hpp" #include #include @@ -43,7 +43,7 @@ namespace firestarter::x86::payload { class X86Payload : public firestarter::payload::Payload { private: /// This list contains the features (cpu extenstions) that are requied to execute the payload. - std::list FeatureRequests; + X86CpuFeatures FeatureRequests; /// The mapping from instructions to the number of flops per instruction. This map is required to have an entry for /// every instruction. @@ -63,32 +63,25 @@ class X86Payload : public firestarter::payload::Payload { /// to have an entry for every instruction. /// \arg InstructionMemory The mapping from instructions to the size of main memory accesses for this instuction. This /// map is not required to contain all instructions. - X86Payload(std::initializer_list FeatureRequests, std::string Name, - unsigned RegisterSize, unsigned RegisterCount, std::map&& InstructionFlops, + X86Payload(X86CpuFeatures FeatureRequests, std::string Name, unsigned RegisterSize, unsigned RegisterCount, + std::map&& InstructionFlops, std::map&& InstructionMemory) noexcept : Payload(std::move(Name), RegisterSize, RegisterCount) - , FeatureRequests(FeatureRequests) + , FeatureRequests(std::move(FeatureRequests)) , InstructionFlops(std::move(InstructionFlops)) , InstructionMemory(std::move(InstructionMemory)) {} -private: - /// Check if this payload is available on the current system. This is equivalent to checking if the supplied Topology - /// contains all features that are in FeatureRequests. - /// \arg Topology The CPUTopology that is used to check agains if this payload is supported. - /// \returns true if the payload is supported on the given CPUTopology. - [[nodiscard]] auto isAvailable(const ProcessorInformation& Topology) const -> bool final { - const auto* FinalTopology = dynamic_cast(&Topology); - assert(FinalTopology && "isAvailable not called with const X86CPUTopology*"); - - bool Available = true; - - for (auto const& Feature : FeatureRequests) { - Available &= FinalTopology->featuresAsmjit().has(Feature); - } - - return Available; + /// Check if this payload is available on the current system. This is equivalent to checking if the supplied features + /// contains all that are requested by this payload. + /// \arg CpuFeatures Features that this payload requires to check agains if this payload is supported. + /// \returns true if the payload is supported on the system with the given features. + [[nodiscard]] auto isAvailable(const CpuFeatures& Features) const -> bool final { + return Features.hasAll(FeatureRequests); }; + /// The features that are required for this payload + [[nodiscard]] auto featureRequests() const -> const auto& { return FeatureRequests; } + protected: /// Print the generated assembler Code of asmjit /// \arg Builder The builder that contains the assembler code. diff --git a/include/firestarter/X86/Payload/ZENFMAPayload.hpp b/include/firestarter/X86/Payload/ZENFMAPayload.hpp index 648fb0c9..b9aa0f77 100644 --- a/include/firestarter/X86/Payload/ZENFMAPayload.hpp +++ b/include/firestarter/X86/Payload/ZENFMAPayload.hpp @@ -21,6 +21,7 @@ #pragma once +#include "asmjit/core/cpuinfo.h" #include "firestarter/X86/Payload/X86Payload.hpp" namespace firestarter::x86::payload { @@ -29,7 +30,9 @@ namespace firestarter::x86::payload { class ZENFMAPayload final : public X86Payload { public: ZENFMAPayload() noexcept - : X86Payload(/*FeatureRequests=*/{asmjit::CpuFeatures::X86::Id::kAVX, asmjit::CpuFeatures::X86::Id::kFMA}, + : X86Payload(/*FeatureRequests=*/X86CpuFeatures() + .add(asmjit::CpuFeatures::X86::Id::kAVX) + .add(asmjit::CpuFeatures::X86::Id::kFMA), /*Name=*/"ZENFMA", /*RegisterSize=*/4, /*RegisterCount=*/16, /*InstructionFlops=*/{{"REG", 8}, {"L1_LS", 8}, {"L2_L", 8}, {"L3_L", 8}, {"RAM_L", 8}}, /*InstructionMemory=*/{{"RAM_L", 64}}) {} diff --git a/include/firestarter/X86/Platform/X86PlatformConfig.hpp b/include/firestarter/X86/Platform/X86PlatformConfig.hpp index a81cb711..f62c14d5 100644 --- a/include/firestarter/X86/Platform/X86PlatformConfig.hpp +++ b/include/firestarter/X86/Platform/X86PlatformConfig.hpp @@ -76,7 +76,7 @@ class X86PlatformConfig : public firestarter::platform::PlatformConfig { // in the models list of the config and if the config is available on the current platform. return Family == FinalTopology->familyId() && (std::find(Models.begin(), Models.end(), FinalTopology->modelId()) != Models.end()) && - payload()->isAvailable(*Topology); + payload()->isAvailable(Topology->cpuFeatures()); } }; diff --git a/include/firestarter/X86/X86CpuFeatures.hpp b/include/firestarter/X86/X86CpuFeatures.hpp new file mode 100644 index 00000000..8a303d5f --- /dev/null +++ b/include/firestarter/X86/X86CpuFeatures.hpp @@ -0,0 +1,63 @@ +/****************************************************************************** + * FIRESTARTER - A Processor Stress Test Utility + * Copyright (C) 2024 TU Dresden, Center for Information Services and High + * Performance Computing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Contact: daniel.hackenberg@tu-dresden.de + *****************************************************************************/ + +#pragma once + +#include "firestarter/CpuFeatures.hpp" + +#include +#include +#include + +namespace firestarter::x86 { + +/// This class models the cpu features on the x86_64 platform. +class X86CpuFeatures : public CpuFeatures { +private: + /// This list contains the features (cpu extenstions) that are requied to execute the payload. + asmjit::CpuFeatures AsmjitFeatures; + +public: + X86CpuFeatures() = default; + explicit X86CpuFeatures(const asmjit::CpuFeatures& FeatureRequests) + : AsmjitFeatures(FeatureRequests) {} + + explicit operator const asmjit::CpuFeatures&() const noexcept { return AsmjitFeatures; } + + [[nodiscard]] auto add(asmjit::CpuFeatures::X86::Id Id) -> X86CpuFeatures& { + AsmjitFeatures.add(Id); + return *this; + } + + /// Check if this class has all features which are given in the argument. + /// \arg Features The features which should be check if they are available. + /// \returns true if this class has all features given in the argument. + [[nodiscard]] auto hasAll(const CpuFeatures& Features) const -> bool override { + const auto* DerivedFeatures = dynamic_cast(&Features); + if (!DerivedFeatures) { + throw std::runtime_error("Features is not of the correct type X86CpuFeatures"); + } + + return AsmjitFeatures.hasAll(DerivedFeatures->AsmjitFeatures); + } +}; + +} // namespace firestarter::x86 diff --git a/src/firestarter/FunctionSelection.cpp b/src/firestarter/FunctionSelection.cpp index b4164559..4b8a2ff8 100644 --- a/src/firestarter/FunctionSelection.cpp +++ b/src/firestarter/FunctionSelection.cpp @@ -39,7 +39,7 @@ auto FunctionSelection::selectAvailableFunction(unsigned FunctionId, const Proce for (const auto& Platform : platform::PlatformConfigAndThreads::fromPlatformConfigs(platformConfigs())) { // the selected function if (Id == FunctionId) { - if (!Platform.Config->payload()->isAvailable(ProcessorInfos)) { + if (!Platform.Config->payload()->isAvailable(ProcessorInfos.cpuFeatures())) { const auto ErrorString = "Function " + std::to_string(FunctionId) + " (\"" + Platform.Config->functionName(Platform.ThreadCount) + "\") requires " + Platform.Config->payload()->name() + ", which is not supported by the processor."; @@ -89,7 +89,7 @@ auto FunctionSelection::selectDefaultOrFallbackFunction(const ProcessorInformati // loop over available implementation and check if they are marked as // fallback for (const auto& FallbackPlatformConfigPtr : fallbackPlatformConfigs()) { - if (FallbackPlatformConfigPtr->payload()->isAvailable(ProcessorInfos)) { + if (FallbackPlatformConfigPtr->payload()->isAvailable(ProcessorInfos.cpuFeatures())) { unsigned SelectedThreadsPerCore{}; // find the fallback implementation with the correct thread per core count or select the first available thread @@ -138,7 +138,8 @@ void FunctionSelection::printFunctionSummary(const ProcessorInformation& Process auto Id = 1U; for (const auto& Platform : platform::PlatformConfigAndThreads::fromPlatformConfigs(platformConfigs())) { - const char* Available = (Platform.Config->payload()->isAvailable(ProcessorInfos) || ForceYes) ? "yes" : "no"; + const char* Available = + (Platform.Config->payload()->isAvailable(ProcessorInfos.cpuFeatures()) || ForceYes) ? "yes" : "no"; const auto& FunctionName = Platform.Config->functionName(Platform.ThreadCount); const auto& InstructionGroupsString = Platform.Config->constRef().settings().groups(); diff --git a/src/firestarter/ProcessorInformation.cpp b/src/firestarter/ProcessorInformation.cpp index e1ea9df8..8c66cc24 100644 --- a/src/firestarter/ProcessorInformation.cpp +++ b/src/firestarter/ProcessorInformation.cpp @@ -20,7 +20,6 @@ *****************************************************************************/ #include "firestarter/ProcessorInformation.hpp" -#include "firestarter/Firestarter.hpp" #include "firestarter/Logging/Log.hpp" #include @@ -49,8 +48,9 @@ void ProcessorInformation::print() const { << " supported features: " << Ss.str(); } -ProcessorInformation::ProcessorInformation(std::string Architecture) - : Architecture(std::move(Architecture)) { +ProcessorInformation::ProcessorInformation(std::string Architecture, std::unique_ptr&& Features) + : Features(std::move(Features)) + , Architecture(std::move(Architecture)) { // get vendor, processor name and clockrate for linux #if defined(linux) || defined(__linux__) diff --git a/src/firestarter/X86/X86ProcessorInformation.cpp b/src/firestarter/X86/X86ProcessorInformation.cpp index 5cdd57d2..42f336fe 100644 --- a/src/firestarter/X86/X86ProcessorInformation.cpp +++ b/src/firestarter/X86/X86ProcessorInformation.cpp @@ -21,6 +21,7 @@ #include "firestarter/X86/X86ProcessorInformation.hpp" #include "firestarter/Logging/Log.hpp" +#include "firestarter/X86/X86CpuFeatures.hpp" #include @@ -34,7 +35,7 @@ namespace firestarter::x86 { X86ProcessorInformation::X86ProcessorInformation() - : ProcessorInformation("x86_64") + : ProcessorInformation("x86_64", std::make_unique(asmjit::CpuInfo::host().features())) , CpuInfo(asmjit::CpuInfo::host()) , Vendor(CpuInfo.vendor()) { diff --git a/test/UnitTests/CMakeLists.txt b/test/UnitTests/CMakeLists.txt index c4b35248..1106a517 100644 --- a/test/UnitTests/CMakeLists.txt +++ b/test/UnitTests/CMakeLists.txt @@ -1,6 +1,8 @@ add_executable(UnitTests CpuBindTest.cpp InstructionGroupsTest.cpp + X86CpuFeaturesTest.cpp + X86PayloadTest.cpp ) target_link_libraries(UnitTests diff --git a/test/UnitTests/X86CpuFeaturesTest.cpp b/test/UnitTests/X86CpuFeaturesTest.cpp new file mode 100644 index 00000000..a9657133 --- /dev/null +++ b/test/UnitTests/X86CpuFeaturesTest.cpp @@ -0,0 +1,46 @@ +/****************************************************************************** + * FIRESTARTER - A Processor Stress Test Utility + * Copyright (C) 2024 TU Dresden, Center for Information Services and High + * Performance Computing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Contact: daniel.hackenberg@tu-dresden.de + *****************************************************************************/ + +#include "firestarter/X86/X86CpuFeatures.hpp" + +#include +#include + +class InvalidCpuFeatures : public firestarter::CpuFeatures { + [[nodiscard]] auto hasAll(const CpuFeatures& /*Features*/) const -> bool override { return true; }; +}; + +TEST(X86CpuFeatures, X86CpuFeaturesAllowed) { + firestarter::x86::X86CpuFeatures Features{}; + + EXPECT_NO_THROW((void)Features.hasAll(Features)); + EXPECT_ANY_THROW((void)Features.hasAll(InvalidCpuFeatures())); +} + +TEST(X86CpuFeatures, CheckHasAll) { + const auto Features = + firestarter::x86::X86CpuFeatures().add(asmjit::CpuFeatures::X86::kAVX2).add(asmjit::CpuFeatures::X86::kAVX512_F); + + EXPECT_FALSE(Features.hasAll(firestarter::x86::X86CpuFeatures().add(asmjit::CpuFeatures::X86::kAVX))); + EXPECT_TRUE(Features.hasAll(firestarter::x86::X86CpuFeatures().add(asmjit::CpuFeatures::X86::kAVX2))); + EXPECT_TRUE(Features.hasAll(firestarter::x86::X86CpuFeatures().add(asmjit::CpuFeatures::X86::kAVX512_F))); + EXPECT_TRUE(Features.hasAll(Features)); +} \ No newline at end of file diff --git a/test/UnitTests/X86PayloadTest.cpp b/test/UnitTests/X86PayloadTest.cpp new file mode 100644 index 00000000..23cf48af --- /dev/null +++ b/test/UnitTests/X86PayloadTest.cpp @@ -0,0 +1,72 @@ +/****************************************************************************** + * FIRESTARTER - A Processor Stress Test Utility + * Copyright (C) 2024 TU Dresden, Center for Information Services and High + * Performance Computing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Contact: daniel.hackenberg@tu-dresden.de + *****************************************************************************/ + +#include "firestarter/X86/Payload/X86Payload.hpp" + +#include +#include + +class X86PayloadTest : public firestarter::x86::payload::X86Payload { +public: + X86PayloadTest() + : firestarter::x86::payload::X86Payload( + /*FeatureRequests=*/firestarter::x86::X86CpuFeatures() + .add(asmjit::CpuFeatures::X86::kAVX2) + .add(asmjit::CpuFeatures::X86::kAVX512_F), + /*Name=*/"X86Payload", /*RegisterSize=*/0, + /*RegisterCount=*/0, + /*InstructionFlops=*/ + {}, + /*InstructionMemory=*/{}) {} + + void init(double* /*MemoryAddr*/, uint64_t /*BufferSize*/) const override {} + + [[nodiscard]] auto compilePayload(const firestarter::payload::PayloadSettings& /*Settings*/, bool /*DumpRegisters*/, + bool /*ErrorDetection*/, bool /*PrintAssembler*/) const + -> firestarter::payload::CompiledPayload::UniquePtr override { + return {nullptr, nullptr}; + } +}; + +class TrueCpuFeatures : public firestarter::CpuFeatures { + [[nodiscard]] auto hasAll(const CpuFeatures& /*Features*/) const -> bool override { return true; }; +}; + +class FalseCpuFeatures : public firestarter::CpuFeatures { + [[nodiscard]] auto hasAll(const CpuFeatures& /*Features*/) const -> bool override { return false; }; +}; + +TEST(X86PayloadTest, CpuFeatureHasAllReturned) { + EXPECT_TRUE(X86PayloadTest().isAvailable(TrueCpuFeatures())); + EXPECT_FALSE(X86PayloadTest().isAvailable(FalseCpuFeatures())); +} + +TEST(X86CpuFeatures, CheckIsAvailable) { + EXPECT_FALSE(X86PayloadTest().isAvailable(firestarter::x86::X86CpuFeatures().add(asmjit::CpuFeatures::X86::kAVX))); + EXPECT_FALSE(X86PayloadTest().isAvailable(firestarter::x86::X86CpuFeatures().add(asmjit::CpuFeatures::X86::kAVX2))); + EXPECT_FALSE( + X86PayloadTest().isAvailable(firestarter::x86::X86CpuFeatures().add(asmjit::CpuFeatures::X86::kAVX512_F))); + EXPECT_TRUE(X86PayloadTest().isAvailable(X86PayloadTest().featureRequests())); + EXPECT_TRUE(X86PayloadTest().isAvailable(firestarter::x86::X86CpuFeatures() + .add(asmjit::CpuFeatures::X86::kAVX) + .add(asmjit::CpuFeatures::X86::kAVX2) + .add(asmjit::CpuFeatures::X86::kAVX512_F))); +} \ No newline at end of file From 6ecbf51efd3c04fbae21202aebe970fe40791c57 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Sat, 14 Dec 2024 12:30:02 +0100 Subject: [PATCH 28/31] wrapp x86 model information in X86Model class. test X86Model class. test X86PlafromConfig::isDefault. --- include/firestarter/CpuModel.hpp | 42 ++++++++++ .../firestarter/Platform/PlatformConfig.hpp | 13 ++- include/firestarter/ProcessorInformation.hpp | 9 +- .../X86/Platform/BulldozerConfig.hpp | 5 +- .../X86/Platform/HaswellConfig.hpp | 5 +- .../X86/Platform/HaswellEPConfig.hpp | 3 +- .../X86/Platform/KnightsLandingConfig.hpp | 3 +- .../firestarter/X86/Platform/NaplesConfig.hpp | 4 +- .../X86/Platform/NehalemConfig.hpp | 4 +- .../X86/Platform/NehalemEPConfig.hpp | 3 +- .../firestarter/X86/Platform/RomeConfig.hpp | 3 +- .../X86/Platform/SandyBridgeConfig.hpp | 3 +- .../X86/Platform/SandyBridgeEPConfig.hpp | 3 +- .../X86/Platform/SkylakeConfig.hpp | 3 +- .../X86/Platform/SkylakeSPConfig.hpp | 3 +- .../X86/Platform/X86PlatformConfig.hpp | 40 ++++----- include/firestarter/X86/X86CpuModel.hpp | 70 ++++++++++++++++ .../X86/X86ProcessorInformation.hpp | 8 -- src/firestarter/Firestarter.cpp | 5 +- src/firestarter/FunctionSelection.cpp | 2 +- src/firestarter/ProcessorInformation.cpp | 4 +- .../X86/X86ProcessorInformation.cpp | 8 +- test/UnitTests/CMakeLists.txt | 2 + test/UnitTests/X86CpuFeaturesTest.cpp | 4 + test/UnitTests/X86CpuModelTest.cpp | 66 +++++++++++++++ test/UnitTests/X86PayloadTest.cpp | 4 + test/UnitTests/X86PlatformConfigTest.cpp | 83 +++++++++++++++++++ 27 files changed, 342 insertions(+), 60 deletions(-) create mode 100644 include/firestarter/CpuModel.hpp create mode 100644 include/firestarter/X86/X86CpuModel.hpp create mode 100644 test/UnitTests/X86CpuModelTest.cpp create mode 100644 test/UnitTests/X86PlatformConfigTest.cpp diff --git a/include/firestarter/CpuModel.hpp b/include/firestarter/CpuModel.hpp new file mode 100644 index 00000000..4cfeeacc --- /dev/null +++ b/include/firestarter/CpuModel.hpp @@ -0,0 +1,42 @@ +/****************************************************************************** + * FIRESTARTER - A Processor Stress Test Utility + * Copyright (C) 2024 TU Dresden, Center for Information Services and High + * Performance Computing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Contact: daniel.hackenberg@tu-dresden.de + *****************************************************************************/ + +#pragma once + +namespace firestarter { + +/// Abstract class that defines the methods required to check if one cpu model is equal to another +class CpuModel { +public: + CpuModel() = default; + virtual ~CpuModel() = default; + + /// \arg Other The model to which operator < should be checked. + /// \return true if this is less than other + [[nodiscard]] virtual auto operator<(const CpuModel& Other) const -> bool = 0; + + /// Check if two models match. + /// \arg Other The model to which equality should be checked. + /// \return true if this and the other model match + [[nodiscard]] virtual auto operator==(const CpuModel& Other) const -> bool = 0; +}; + +} // namespace firestarter diff --git a/include/firestarter/Platform/PlatformConfig.hpp b/include/firestarter/Platform/PlatformConfig.hpp index 3eda4783..19c3d21d 100644 --- a/include/firestarter/Platform/PlatformConfig.hpp +++ b/include/firestarter/Platform/PlatformConfig.hpp @@ -22,6 +22,7 @@ #pragma once #include "firestarter/Config/InstructionGroups.hpp" +#include "firestarter/CpuModel.hpp" #include "firestarter/Logging/Log.hpp" #include "firestarter/Payload/Payload.hpp" #include "firestarter/ProcessorInformation.hpp" @@ -59,19 +60,15 @@ class PlatformConfig { [[nodiscard]] auto payload() const -> const auto& { return Payload; } /// Check if this platform is available and the default on the current system. - /// \arg Topology The reference to the CPUTopology that is used to check agains if this payload is supported. - /// \returns true if the platform is the default one for a given CPUTopology. - [[nodiscard]] auto isDefault(const ProcessorInformation& Topology) const -> bool { return isDefault(&Topology); } + /// \arg Model The reference to the cpu model that is used to check if this config is the default. + /// \arg CpuFeatures Features that this payload requires to check agains if this payload is supported. + /// \returns true if the platform is the default one. + [[nodiscard]] virtual auto isDefault(const CpuModel& Model, const CpuFeatures& Features) const -> bool = 0; protected: /// Non const Getter for the settings of the platform. [[nodiscard]] auto settings() -> payload::PayloadSettings& { return Settings; } - /// Check if this platform is available and the default on the current system. - /// \arg Topology The pointer to the CPUTopology that is used to check agains if this payload is supported. - /// \returns true if the platform is the default one for a given CPUTopology. - [[nodiscard]] virtual auto isDefault(const ProcessorInformation*) const -> bool = 0; - public: PlatformConfig() = delete; diff --git a/include/firestarter/ProcessorInformation.hpp b/include/firestarter/ProcessorInformation.hpp index 2eeaa097..c2c1c46f 100644 --- a/include/firestarter/ProcessorInformation.hpp +++ b/include/firestarter/ProcessorInformation.hpp @@ -22,6 +22,7 @@ #pragma once #include "firestarter/CpuFeatures.hpp" +#include "firestarter/CpuModel.hpp" #include #include @@ -38,7 +39,8 @@ namespace firestarter { /// This class models the properties of a processor. class ProcessorInformation { public: - explicit ProcessorInformation(std::string Architecture, std::unique_ptr&& Features); + explicit ProcessorInformation(std::string Architecture, std::unique_ptr&& Features, + std::unique_ptr&& Model); virtual ~ProcessorInformation() = default; /// Getter for the clockrate in Hz @@ -56,6 +58,9 @@ class ProcessorInformation { /// Getter for the cpu features abstraction [[nodiscard]] auto cpuFeatures() const -> const CpuFeatures& { return *Features; } + /// Getter for the cpu model abstraction + [[nodiscard]] auto cpuModel() const -> const CpuModel& { return *Model; } + /// Print the information about this process to a stream. void print() const; @@ -75,6 +80,8 @@ class ProcessorInformation { std::string Vendor; /// The cpu features of this processor. std::unique_ptr Features; + /// The cpu model of this processor. + std::unique_ptr Model; /// Helper function to open a filepath and return a stringstream with its contents. /// \arg FilePath The file to open diff --git a/include/firestarter/X86/Platform/BulldozerConfig.hpp b/include/firestarter/X86/Platform/BulldozerConfig.hpp index a1496e20..89209824 100644 --- a/include/firestarter/X86/Platform/BulldozerConfig.hpp +++ b/include/firestarter/X86/Platform/BulldozerConfig.hpp @@ -29,7 +29,10 @@ class BulldozerConfig final : public X86PlatformConfig { public: BulldozerConfig() noexcept : X86PlatformConfig( - /*Name=*/"BLD_OPTERON", /*Family=*/21, /*Models=*/{1, 2, 3}, + /*Name=*/"BLD_OPTERON", + /*RequestedModels=*/ + {X86CpuModel(/*FamilyId=*/21, /*ModelId=*/1), X86CpuModel(/*FamilyId=*/21, /*ModelId=*/2), + X86CpuModel(/*FamilyId=*/21, /*ModelId=*/3)}, /*Settings=*/ firestarter::payload::PayloadSettings( /*Threads=*/{1}, /*DataCacheBufferSize=*/{16384, 1048576, 786432}, /*RamBufferSize=*/104857600, diff --git a/include/firestarter/X86/Platform/HaswellConfig.hpp b/include/firestarter/X86/Platform/HaswellConfig.hpp index e117b20d..09c390e5 100644 --- a/include/firestarter/X86/Platform/HaswellConfig.hpp +++ b/include/firestarter/X86/Platform/HaswellConfig.hpp @@ -29,7 +29,10 @@ class HaswellConfig final : public X86PlatformConfig { public: HaswellConfig() noexcept : X86PlatformConfig( - /*Name=*/"HSW_COREI", /*Family=*/6, /*Models=*/{60, 61, 69, 70, 71}, + /*Name=*/"HSW_COREI", /*RequestedModels=*/ + {X86CpuModel(/*FamilyId=*/6, /*ModelId=*/60), X86CpuModel(/*FamilyId=*/6, /*ModelId=*/61), + X86CpuModel(/*FamilyId=*/6, /*ModelId=*/69), X86CpuModel(/*FamilyId=*/6, /*ModelId=*/70), + X86CpuModel(/*FamilyId=*/6, /*ModelId=*/71)}, /*Settings=*/ firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 1572864}, /*RamBufferSize=*/104857600, diff --git a/include/firestarter/X86/Platform/HaswellEPConfig.hpp b/include/firestarter/X86/Platform/HaswellEPConfig.hpp index d0b7f014..977eab72 100644 --- a/include/firestarter/X86/Platform/HaswellEPConfig.hpp +++ b/include/firestarter/X86/Platform/HaswellEPConfig.hpp @@ -29,7 +29,8 @@ class HaswellEPConfig final : public X86PlatformConfig { public: HaswellEPConfig() noexcept : X86PlatformConfig( - /*Name=*/"HSW_XEONEP", /*Family=*/6, /*Models=*/{63, 79}, + /*Name=*/"HSW_XEONEP", /*RequestedModels=*/ + {X86CpuModel(/*FamilyId=*/6, /*ModelId=*/63), X86CpuModel(/*FamilyId=*/6, /*ModelId=*/79)}, /*Settings=*/ firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 2621440}, diff --git a/include/firestarter/X86/Platform/KnightsLandingConfig.hpp b/include/firestarter/X86/Platform/KnightsLandingConfig.hpp index e46ebdc5..ac020436 100644 --- a/include/firestarter/X86/Platform/KnightsLandingConfig.hpp +++ b/include/firestarter/X86/Platform/KnightsLandingConfig.hpp @@ -28,7 +28,8 @@ namespace firestarter::x86::platform { class KnightsLandingConfig final : public X86PlatformConfig { public: KnightsLandingConfig() noexcept - : X86PlatformConfig(/*Name=*/"KNL_XEONPHI", /*Family=*/6, /*Models=*/{87}, + : X86PlatformConfig(/*Name=*/"KNL_XEONPHI", /*RequestedModels=*/ + {X86CpuModel(/*FamilyId=*/6, /*ModelId=*/87)}, /*Settings=*/ firestarter::payload::PayloadSettings( /*Threads=*/{4}, /*DataCacheBufferSize=*/{32768, 524288, 236279125}, diff --git a/include/firestarter/X86/Platform/NaplesConfig.hpp b/include/firestarter/X86/Platform/NaplesConfig.hpp index 5bbb25f5..7411899e 100644 --- a/include/firestarter/X86/Platform/NaplesConfig.hpp +++ b/include/firestarter/X86/Platform/NaplesConfig.hpp @@ -29,7 +29,9 @@ class NaplesConfig final : public X86PlatformConfig { public: NaplesConfig() noexcept : X86PlatformConfig( - /*Name=*/"ZEN_EPYC", /*Family=*/23, /*Models=*/{1, 8, 17, 24}, + /*Name=*/"ZEN_EPYC", /*RequestedModels=*/ + {X86CpuModel(/*FamilyId=*/23, /*ModelId=*/1), X86CpuModel(/*FamilyId=*/23, /*ModelId=*/8), + X86CpuModel(/*FamilyId=*/23, /*ModelId=*/17), X86CpuModel(/*FamilyId=*/23, /*ModelId=*/24)}, /*Settings=*/ firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{65536, 524288, 2097152}, /*RamBufferSize=*/104857600, diff --git a/include/firestarter/X86/Platform/NehalemConfig.hpp b/include/firestarter/X86/Platform/NehalemConfig.hpp index c1f0e3b3..638ec27a 100644 --- a/include/firestarter/X86/Platform/NehalemConfig.hpp +++ b/include/firestarter/X86/Platform/NehalemConfig.hpp @@ -29,7 +29,9 @@ class NehalemConfig final : public X86PlatformConfig { public: NehalemConfig() noexcept : X86PlatformConfig( - /*Name=*/"NHM_COREI", /*Family=*/6, /*Models=*/{30, 37, 23}, + /*Name=*/"NHM_COREI", /*RequestedModels=*/ + {X86CpuModel(/*FamilyId=*/6, /*ModelId=*/30), X86CpuModel(/*FamilyId=*/6, /*ModelId=*/37), + X86CpuModel(/*FamilyId=*/6, /*ModelId=*/23)}, /*Settings=*/ firestarter::payload::PayloadSettings(/*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 1572864}, /*RamBufferSize=*/104857600, /*Lines=*/1536, diff --git a/include/firestarter/X86/Platform/NehalemEPConfig.hpp b/include/firestarter/X86/Platform/NehalemEPConfig.hpp index c02e7f47..648dd681 100644 --- a/include/firestarter/X86/Platform/NehalemEPConfig.hpp +++ b/include/firestarter/X86/Platform/NehalemEPConfig.hpp @@ -28,7 +28,8 @@ namespace firestarter::x86::platform { class NehalemEPConfig final : public X86PlatformConfig { public: NehalemEPConfig() noexcept - : X86PlatformConfig(/*Name=*/"NHM_XEONEP", /*Family=*/6, /*Models=*/{26, 44}, + : X86PlatformConfig(/*Name=*/"NHM_XEONEP", /*RequestedModels=*/ + {X86CpuModel(/*FamilyId=*/6, /*ModelId=*/26), X86CpuModel(/*FamilyId=*/6, /*ModelId=*/44)}, /*Settings=*/ firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 2097152}, diff --git a/include/firestarter/X86/Platform/RomeConfig.hpp b/include/firestarter/X86/Platform/RomeConfig.hpp index 5a2d04e4..bd0e156f 100644 --- a/include/firestarter/X86/Platform/RomeConfig.hpp +++ b/include/firestarter/X86/Platform/RomeConfig.hpp @@ -29,7 +29,8 @@ class RomeConfig final : public X86PlatformConfig { public: RomeConfig() noexcept : X86PlatformConfig( - /*Name=*/"ZEN_2_EPYC", /*Family=*/23, /*Models=*/{49}, + /*Name=*/"ZEN_2_EPYC", /*RequestedModels=*/ + {X86CpuModel(/*FamilyId=*/23, /*ModelId=*/49)}, /*Settings=*/ firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 524288, 2097152}, /*RamBufferSize=*/104857600, diff --git a/include/firestarter/X86/Platform/SandyBridgeConfig.hpp b/include/firestarter/X86/Platform/SandyBridgeConfig.hpp index 50fd8a00..ec08244f 100644 --- a/include/firestarter/X86/Platform/SandyBridgeConfig.hpp +++ b/include/firestarter/X86/Platform/SandyBridgeConfig.hpp @@ -29,7 +29,8 @@ class SandyBridgeConfig final : public X86PlatformConfig { public: SandyBridgeConfig() noexcept : X86PlatformConfig( - /*Name=*/"SNB_COREI", /*Family=*/6, /*Models=*/{42, 58}, + /*Name=*/"SNB_COREI", /*RequestedModels=*/ + {X86CpuModel(/*FamilyId=*/6, /*ModelId=*/42), X86CpuModel(/*FamilyId=*/6, /*ModelId=*/58)}, /*Settings=*/ firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 1572864}, /*RamBufferSize=*/104857600, diff --git a/include/firestarter/X86/Platform/SandyBridgeEPConfig.hpp b/include/firestarter/X86/Platform/SandyBridgeEPConfig.hpp index 5f6ec9ce..3b9625b6 100644 --- a/include/firestarter/X86/Platform/SandyBridgeEPConfig.hpp +++ b/include/firestarter/X86/Platform/SandyBridgeEPConfig.hpp @@ -29,7 +29,8 @@ class SandyBridgeEPConfig final : public X86PlatformConfig { public: SandyBridgeEPConfig() noexcept : X86PlatformConfig( - /*Name=*/"SNB_XEONEP", /*Family=*/6, /*Models=*/{45, 62}, + /*Name=*/"SNB_XEONEP", /*RequestedModels=*/ + {X86CpuModel(/*FamilyId=*/6, /*ModelId=*/45), X86CpuModel(/*FamilyId=*/6, /*ModelId=*/62)}, /*Settings=*/ firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 2621440}, /*RamBufferSize=*/104857600, diff --git a/include/firestarter/X86/Platform/SkylakeConfig.hpp b/include/firestarter/X86/Platform/SkylakeConfig.hpp index 843151db..3d0b38f1 100644 --- a/include/firestarter/X86/Platform/SkylakeConfig.hpp +++ b/include/firestarter/X86/Platform/SkylakeConfig.hpp @@ -29,7 +29,8 @@ class SkylakeConfig final : public X86PlatformConfig { public: SkylakeConfig() noexcept : X86PlatformConfig( - /*Name=*/"SKL_COREI", /*Family=*/6, /*Models=*/{78, 94}, + /*Name=*/"SKL_COREI", /*RequestedModels=*/ + {X86CpuModel(/*FamilyId=*/6, /*ModelId=*/78), X86CpuModel(/*FamilyId=*/6, /*ModelId=*/94)}, /*Settings=*/ firestarter::payload::PayloadSettings( /*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 262144, 1572864}, diff --git a/include/firestarter/X86/Platform/SkylakeSPConfig.hpp b/include/firestarter/X86/Platform/SkylakeSPConfig.hpp index c3b50c13..0703c223 100644 --- a/include/firestarter/X86/Platform/SkylakeSPConfig.hpp +++ b/include/firestarter/X86/Platform/SkylakeSPConfig.hpp @@ -28,7 +28,8 @@ namespace firestarter::x86::platform { class SkylakeSPConfig final : public X86PlatformConfig { public: SkylakeSPConfig() noexcept - : X86PlatformConfig(/*Name=*/"SKL_XEONEP", /*Family=*/6, /*Models=*/{85}, + : X86PlatformConfig(/*Name=*/"SKL_XEONEP", /*RequestedModels=*/ + {X86CpuModel(/*FamilyId=*/6, /*ModelId=*/85)}, /*Settings=*/ firestarter::payload::PayloadSettings(/*Threads=*/{1, 2}, /*DataCacheBufferSize=*/{32768, 1048576, 1441792}, diff --git a/include/firestarter/X86/Platform/X86PlatformConfig.hpp b/include/firestarter/X86/Platform/X86PlatformConfig.hpp index f62c14d5..af909a4d 100644 --- a/include/firestarter/X86/Platform/X86PlatformConfig.hpp +++ b/include/firestarter/X86/Platform/X86PlatformConfig.hpp @@ -22,30 +22,27 @@ #pragma once #include "firestarter/Platform/PlatformConfig.hpp" -#include "firestarter/ProcessorInformation.hpp" -#include "firestarter/X86/X86ProcessorInformation.hpp" +#include "firestarter/X86/X86CpuModel.hpp" +#include namespace firestarter::x86::platform { /// Models a platform config that is the default based on x86 CPU family and model ids. class X86PlatformConfig : public firestarter::platform::PlatformConfig { private: - /// The famility id of the processor for which this is the default platform config. - unsigned Family; - /// The list of model ids in combination with the family for which this is the default platform config. - std::list Models; + /// The set of requested cpu models + std::set RequestedModels; public: - X86PlatformConfig(std::string Name, unsigned Family, std::list&& Models, + X86PlatformConfig(std::string Name, std::set&& RequestedModels, firestarter::payload::PayloadSettings&& Settings, std::shared_ptr&& Payload) noexcept : PlatformConfig(std::move(Name), std::move(Settings), std::move(Payload)) - , Family(Family) - , Models(std::move(Models)) {} + , RequestedModels(std::move(RequestedModels)) {} /// Clone a the platform config. [[nodiscard]] auto clone() const -> std::unique_ptr final { - auto Ptr = std::make_unique(name(), Family, std::list(Models), + auto Ptr = std::make_unique(name(), std::set(RequestedModels), firestarter::payload::PayloadSettings(settings()), std::shared_ptr(payload())); return Ptr; @@ -62,21 +59,14 @@ class X86PlatformConfig : public firestarter::platform::PlatformConfig { return Ptr; } -private: - /// Check if this platform is available and the default on the current system. This is done by checking if the family - /// id in the CPUTopology matches the one saved in Family and if the model id in the CPUTopology is contained in - /// Models. - /// \arg Topology The pointer to the CPUTopology that is used to check agains if this payload is supported. - /// \returns true if the platform is the default one for a given CPUTopology. - [[nodiscard]] auto isDefault(const ProcessorInformation* Topology) const -> bool final { - const auto* FinalTopology = dynamic_cast(Topology); - assert(FinalTopology && "isDefault not called with const X86CPUTopology*"); - - // Check if the family of the topology matches the family of the config, if the model of the topology is contained - // in the models list of the config and if the config is available on the current platform. - return Family == FinalTopology->familyId() && - (std::find(Models.begin(), Models.end(), FinalTopology->modelId()) != Models.end()) && - payload()->isAvailable(Topology->cpuFeatures()); + /// Check if this platform is available and the default on the current system. This is done by checking if the cpu + /// model matches one of the requested ones and that the payload is available with the supplied cpu features. + /// \arg Model The reference to the cpu model that is used to check if this config is the default. + /// \arg CpuFeatures Features that this payload requires to check agains if this payload is supported. + /// \returns true if the platform is the default one. + [[nodiscard]] auto isDefault(const CpuModel& Model, const CpuFeatures& Features) const -> bool override { + const auto ModelIt = std::find(RequestedModels.cbegin(), RequestedModels.cend(), Model); + return ModelIt != RequestedModels.cend() && payload()->isAvailable(Features); } }; diff --git a/include/firestarter/X86/X86CpuModel.hpp b/include/firestarter/X86/X86CpuModel.hpp new file mode 100644 index 00000000..6f99cae2 --- /dev/null +++ b/include/firestarter/X86/X86CpuModel.hpp @@ -0,0 +1,70 @@ +/****************************************************************************** + * FIRESTARTER - A Processor Stress Test Utility + * Copyright (C) 2024 TU Dresden, Center for Information Services and High + * Performance Computing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Contact: daniel.hackenberg@tu-dresden.de + *****************************************************************************/ + +#pragma once + +#include "firestarter/CpuModel.hpp" + +#include +#include +#include + +namespace firestarter::x86 { + +/// This class models the cpu features on the x86_64 platform. +class X86CpuModel : public CpuModel { +private: + /// The x86 family id + unsigned FamilyId; + /// The x86 model id + unsigned ModelId; + +public: + X86CpuModel() = delete; + explicit X86CpuModel(unsigned FamilyId, unsigned ModelId) noexcept + : FamilyId(FamilyId) + , ModelId(ModelId) {} + + /// \arg Other The model to which operator < should be checked. + /// \return true if this is less than other + [[nodiscard]] auto operator<(const CpuModel& Other) const -> bool override { + const auto* DerivedModel = dynamic_cast(&Other); + if (!DerivedModel) { + throw std::runtime_error("Other is not of the correct type X86CpuModel"); + } + + return std::tie(FamilyId, ModelId) < std::tie(DerivedModel->FamilyId, DerivedModel->ModelId); + } + + /// Check if two models match. + /// \arg Other The model to which equality should be checked. + /// \return true if this and the other model match + [[nodiscard]] auto operator==(const CpuModel& Other) const -> bool override { + const auto* DerivedModel = dynamic_cast(&Other); + if (!DerivedModel) { + throw std::runtime_error("Other is not of the correct type X86CpuModel"); + } + + return std::tie(FamilyId, ModelId) == std::tie(DerivedModel->FamilyId, DerivedModel->ModelId); + } +}; + +} // namespace firestarter::x86 diff --git a/include/firestarter/X86/X86ProcessorInformation.hpp b/include/firestarter/X86/X86ProcessorInformation.hpp index b7922a66..d282a38a 100644 --- a/include/firestarter/X86/X86ProcessorInformation.hpp +++ b/include/firestarter/X86/X86ProcessorInformation.hpp @@ -34,8 +34,6 @@ class X86ProcessorInformation final : public ProcessorInformation { /// Getter for the list of CPU features [[nodiscard]] auto features() const -> std::list const& override { return this->FeatureList; } - /// Getter for the CPU features class from asmjit - [[nodiscard]] auto featuresAsmjit() const -> const asmjit::CpuFeatures& { return this->CpuInfo.features(); } /// Getter for the clockrate in Hz [[nodiscard]] auto clockrate() const -> uint64_t override; @@ -43,12 +41,6 @@ class X86ProcessorInformation final : public ProcessorInformation { /// Get the current hardware timestamp [[nodiscard]] auto timestamp() const -> uint64_t override; - /// The family id of the x86 processor - [[nodiscard]] auto familyId() const -> unsigned { return this->CpuInfo.familyId(); } - /// The model id of the x86 processor - [[nodiscard]] auto modelId() const -> unsigned { return this->CpuInfo.modelId(); } - /// The stepping id of the x86 processor - [[nodiscard]] auto stepping() const -> unsigned { return this->CpuInfo.stepping(); } /// The CPU vendor i.e., Intel or AMD. [[nodiscard]] auto vendor() const -> std::string const& final { return Vendor; } /// Get the string containing family, model and stepping ids. diff --git a/src/firestarter/Firestarter.cpp b/src/firestarter/Firestarter.cpp index 4eeaf6da..9e664158 100644 --- a/src/firestarter/Firestarter.cpp +++ b/src/firestarter/Firestarter.cpp @@ -25,7 +25,9 @@ #include "firestarter/Optimizer/Algorithm/NSGA2.hpp" #include "firestarter/Optimizer/History.hpp" #include "firestarter/Optimizer/Problem/CLIArgumentProblem.hpp" +#include "firestarter/X86/X86CpuFeatures.hpp" #include "firestarter/X86/X86FunctionSelection.hpp" +#include "firestarter/X86/X86ProcessorInformation.hpp" #include #include @@ -48,8 +50,7 @@ Firestarter::Firestarter(Config&& ProvidedConfig) if constexpr (firestarter::OptionalFeatures.IsX86) { // Error detection uses crc32 instruction added by the SSE4.2 extension to x86 if (Cfg.ErrorDetection) { - const auto& X86ProcessorInfos = *dynamic_cast(ProcessorInfos.get()); - if (!X86ProcessorInfos.featuresAsmjit().has(asmjit::CpuFeatures::X86::kSSE4_2)) { + if (!ProcessorInfos->cpuFeatures().hasAll(x86::X86CpuFeatures().add(asmjit::CpuFeatures::X86::kSSE4_2))) { throw std::invalid_argument("Option --error-detection requires the crc32 " "instruction added with SSE_4_2.\n"); } diff --git a/src/firestarter/FunctionSelection.cpp b/src/firestarter/FunctionSelection.cpp index 4b8a2ff8..953d475c 100644 --- a/src/firestarter/FunctionSelection.cpp +++ b/src/firestarter/FunctionSelection.cpp @@ -67,7 +67,7 @@ auto FunctionSelection::selectDefaultOrFallbackFunction(const ProcessorInformati for (const auto& Platform : platform::PlatformConfigAndThreads::fromPlatformConfigs(platformConfigs())) { // default function - if (Platform.Config->isDefault(ProcessorInfos)) { + if (Platform.Config->isDefault(ProcessorInfos.cpuModel(), ProcessorInfos.cpuFeatures())) { if (Platform.ThreadCount == ProcessorThreadsPerCore) { return Platform.Config->cloneConcreate(ProcessorICacheSize, Platform.ThreadCount); } diff --git a/src/firestarter/ProcessorInformation.cpp b/src/firestarter/ProcessorInformation.cpp index 8c66cc24..ad86b4d2 100644 --- a/src/firestarter/ProcessorInformation.cpp +++ b/src/firestarter/ProcessorInformation.cpp @@ -48,8 +48,10 @@ void ProcessorInformation::print() const { << " supported features: " << Ss.str(); } -ProcessorInformation::ProcessorInformation(std::string Architecture, std::unique_ptr&& Features) +ProcessorInformation::ProcessorInformation(std::string Architecture, std::unique_ptr&& Features, + std::unique_ptr&& Model) : Features(std::move(Features)) + , Model(std::move(Model)) , Architecture(std::move(Architecture)) { // get vendor, processor name and clockrate for linux diff --git a/src/firestarter/X86/X86ProcessorInformation.cpp b/src/firestarter/X86/X86ProcessorInformation.cpp index 42f336fe..451083de 100644 --- a/src/firestarter/X86/X86ProcessorInformation.cpp +++ b/src/firestarter/X86/X86ProcessorInformation.cpp @@ -22,8 +22,10 @@ #include "firestarter/X86/X86ProcessorInformation.hpp" #include "firestarter/Logging/Log.hpp" #include "firestarter/X86/X86CpuFeatures.hpp" +#include "firestarter/X86/X86CpuModel.hpp" #include +#include #ifdef _MSC_VER #include @@ -35,13 +37,15 @@ namespace firestarter::x86 { X86ProcessorInformation::X86ProcessorInformation() - : ProcessorInformation("x86_64", std::make_unique(asmjit::CpuInfo::host().features())) + : ProcessorInformation( + "x86_64", std::make_unique(asmjit::CpuInfo::host().features()), + std::make_unique(asmjit::CpuInfo::host().familyId(), asmjit::CpuInfo::host().modelId())) , CpuInfo(asmjit::CpuInfo::host()) , Vendor(CpuInfo.vendor()) { { std::stringstream Ss; - Ss << "Family " << familyId() << ", Model " << modelId() << ", Stepping " << stepping(); + Ss << "Family " << CpuInfo.familyId() << ", Model " << CpuInfo.modelId() << ", Stepping " << CpuInfo.stepping(); Model = Ss.str(); } diff --git a/test/UnitTests/CMakeLists.txt b/test/UnitTests/CMakeLists.txt index 1106a517..738a8988 100644 --- a/test/UnitTests/CMakeLists.txt +++ b/test/UnitTests/CMakeLists.txt @@ -2,7 +2,9 @@ add_executable(UnitTests CpuBindTest.cpp InstructionGroupsTest.cpp X86CpuFeaturesTest.cpp + X86CpuModelTest.cpp X86PayloadTest.cpp + X86PlatformConfigTest.cpp ) target_link_libraries(UnitTests diff --git a/test/UnitTests/X86CpuFeaturesTest.cpp b/test/UnitTests/X86CpuFeaturesTest.cpp index a9657133..5b45d923 100644 --- a/test/UnitTests/X86CpuFeaturesTest.cpp +++ b/test/UnitTests/X86CpuFeaturesTest.cpp @@ -24,10 +24,14 @@ #include #include +namespace { + class InvalidCpuFeatures : public firestarter::CpuFeatures { [[nodiscard]] auto hasAll(const CpuFeatures& /*Features*/) const -> bool override { return true; }; }; +} // namespace + TEST(X86CpuFeatures, X86CpuFeaturesAllowed) { firestarter::x86::X86CpuFeatures Features{}; diff --git a/test/UnitTests/X86CpuModelTest.cpp b/test/UnitTests/X86CpuModelTest.cpp new file mode 100644 index 00000000..0c634aa5 --- /dev/null +++ b/test/UnitTests/X86CpuModelTest.cpp @@ -0,0 +1,66 @@ +/****************************************************************************** + * FIRESTARTER - A Processor Stress Test Utility + * Copyright (C) 2024 TU Dresden, Center for Information Services and High + * Performance Computing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Contact: daniel.hackenberg@tu-dresden.de + *****************************************************************************/ + +#include "firestarter/X86/X86CpuModel.hpp" + +#include + +namespace { + +class InvalidCpuModel : public firestarter::CpuModel { + [[nodiscard]] auto operator<(const CpuModel& /*Other*/) const -> bool override { return true; } + + [[nodiscard]] auto operator==(const CpuModel& /*Other*/) const -> bool override { return true; } +}; + +} // namespace + +TEST(X86CpuModel, X86CpuModelAllowed) { + firestarter::x86::X86CpuModel Model(/*FamilyId=*/1, /*ModelId=*/2); + + EXPECT_NO_THROW((void)(Model == Model)); + EXPECT_ANY_THROW((void)(Model == InvalidCpuModel())); +} + +TEST(X86CpuModel, CheckEqual) { + firestarter::x86::X86CpuModel Model(/*FamilyId=*/1, /*ModelId=*/2); + + EXPECT_TRUE(Model == Model); + EXPECT_FALSE(Model == firestarter::x86::X86CpuModel(/*FamilyId=*/1, /*ModelId=*/0)); + EXPECT_FALSE(Model == firestarter::x86::X86CpuModel(/*FamilyId=*/0, /*ModelId=*/2)); + EXPECT_FALSE(Model == firestarter::x86::X86CpuModel(/*FamilyId=*/3, /*ModelId=*/4)); +} + +TEST(X86CpuModel, CheckLess) { + firestarter::x86::X86CpuModel Model(/*FamilyId=*/1, /*ModelId=*/2); + + EXPECT_TRUE(firestarter::x86::X86CpuModel(/*FamilyId=*/0, /*ModelId=*/1) < Model); + EXPECT_TRUE(firestarter::x86::X86CpuModel(/*FamilyId=*/0, /*ModelId=*/2) < Model); + EXPECT_TRUE(firestarter::x86::X86CpuModel(/*FamilyId=*/0, /*ModelId=*/3) < Model); + + EXPECT_TRUE(firestarter::x86::X86CpuModel(/*FamilyId=*/1, /*ModelId=*/1) < Model); + EXPECT_FALSE(Model < Model); + EXPECT_FALSE(firestarter::x86::X86CpuModel(/*FamilyId=*/1, /*ModelId=*/3) < Model); + + EXPECT_FALSE(firestarter::x86::X86CpuModel(/*FamilyId=*/2, /*ModelId=*/1) < Model); + EXPECT_FALSE(firestarter::x86::X86CpuModel(/*FamilyId=*/2, /*ModelId=*/2) < Model); + EXPECT_FALSE(firestarter::x86::X86CpuModel(/*FamilyId=*/2, /*ModelId=*/3) < Model); +} \ No newline at end of file diff --git a/test/UnitTests/X86PayloadTest.cpp b/test/UnitTests/X86PayloadTest.cpp index 23cf48af..3861628f 100644 --- a/test/UnitTests/X86PayloadTest.cpp +++ b/test/UnitTests/X86PayloadTest.cpp @@ -24,6 +24,8 @@ #include #include +namespace { + class X86PayloadTest : public firestarter::x86::payload::X86Payload { public: X86PayloadTest() @@ -54,6 +56,8 @@ class FalseCpuFeatures : public firestarter::CpuFeatures { [[nodiscard]] auto hasAll(const CpuFeatures& /*Features*/) const -> bool override { return false; }; }; +} // namespace + TEST(X86PayloadTest, CpuFeatureHasAllReturned) { EXPECT_TRUE(X86PayloadTest().isAvailable(TrueCpuFeatures())); EXPECT_FALSE(X86PayloadTest().isAvailable(FalseCpuFeatures())); diff --git a/test/UnitTests/X86PlatformConfigTest.cpp b/test/UnitTests/X86PlatformConfigTest.cpp new file mode 100644 index 00000000..912cf34d --- /dev/null +++ b/test/UnitTests/X86PlatformConfigTest.cpp @@ -0,0 +1,83 @@ +/****************************************************************************** + * FIRESTARTER - A Processor Stress Test Utility + * Copyright (C) 2024 TU Dresden, Center for Information Services and High + * Performance Computing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Contact: daniel.hackenberg@tu-dresden.de + *****************************************************************************/ + +#include "firestarter/X86/Platform/X86PlatformConfig.hpp" +#include "firestarter/X86/Payload/X86Payload.hpp" + +#include + +namespace { + +class X86PayloadTest : public firestarter::x86::payload::X86Payload { +public: + X86PayloadTest() + : firestarter::x86::payload::X86Payload( + /*FeatureRequests=*/firestarter::x86::X86CpuFeatures(), + /*Name=*/"X86Payload", /*RegisterSize=*/0, + /*RegisterCount=*/0, + /*InstructionFlops=*/ + {}, + /*InstructionMemory=*/{}) {} + + void init(double* /*MemoryAddr*/, uint64_t /*BufferSize*/) const override {} + + [[nodiscard]] auto compilePayload(const firestarter::payload::PayloadSettings& /*Settings*/, bool /*DumpRegisters*/, + bool /*ErrorDetection*/, bool /*PrintAssembler*/) const + -> firestarter::payload::CompiledPayload::UniquePtr override { + return {nullptr, nullptr}; + } +}; + +class X86PlafromConfigTest : public firestarter::x86::platform::X86PlatformConfig { +public: + inline static const auto Model1 = firestarter::x86::X86CpuModel(/*FamilyId=*/1, /*ModelId=*/2); + inline static const auto Model2 = firestarter::x86::X86CpuModel(/*FamilyId=*/3, /*ModelId=*/4); + inline static const auto InvalidModel = firestarter::x86::X86CpuModel(/*FamilyId=*/5, /*ModelId=*/6); + + X86PlafromConfigTest() + : firestarter::x86::platform::X86PlatformConfig( + "X86PlatformConfig", {Model1, Model2}, + firestarter::payload::PayloadSettings( + /*Threads=*/{}, /*DataCacheBufferSize=*/{}, /*RamBufferSize=*/0, + /*Lines=*/0, /*Groups=*/firestarter::InstructionGroups(firestarter::InstructionGroups::InternalType())), + std::make_shared()) {} +}; + +class TrueCpuFeatures : public firestarter::CpuFeatures { + [[nodiscard]] auto hasAll(const CpuFeatures& /*Features*/) const -> bool override { return true; }; +}; + +class FalseCpuFeatures : public firestarter::CpuFeatures { + [[nodiscard]] auto hasAll(const CpuFeatures& /*Features*/) const -> bool override { return false; }; +}; + +} // namespace + +TEST(X86PlafromConfigTest, CheckIsDefault) { + EXPECT_TRUE(X86PlafromConfigTest().isDefault(X86PlafromConfigTest::Model1, TrueCpuFeatures())); + EXPECT_FALSE(X86PlafromConfigTest().isDefault(X86PlafromConfigTest::Model1, FalseCpuFeatures())); + + EXPECT_TRUE(X86PlafromConfigTest().isDefault(X86PlafromConfigTest::Model2, TrueCpuFeatures())); + EXPECT_FALSE(X86PlafromConfigTest().isDefault(X86PlafromConfigTest::Model2, FalseCpuFeatures())); + + EXPECT_FALSE(X86PlafromConfigTest().isDefault(X86PlafromConfigTest::InvalidModel, TrueCpuFeatures())); + EXPECT_FALSE(X86PlafromConfigTest().isDefault(X86PlafromConfigTest::InvalidModel, FalseCpuFeatures())); +} \ No newline at end of file From 71e42911a9ee663c7a187e3714fbd8efc30883d7 Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Sat, 14 Dec 2024 13:48:43 +0100 Subject: [PATCH 29/31] fix mingw build --- include/firestarter/WindowsCompat.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/firestarter/WindowsCompat.hpp b/include/firestarter/WindowsCompat.hpp index 11ef1329..41e12296 100644 --- a/include/firestarter/WindowsCompat.hpp +++ b/include/firestarter/WindowsCompat.hpp @@ -35,11 +35,15 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" #endif + #if defined(__clang__) #include #elif not(defined(__MINGW32__) || defined(__MINGW64__)) void _mm_mfence() noexcept; +#else +#include #endif + #if not(defined(__INTEL_LLVM_COMPILER)) void __cpuid(int* /*unused*/, int /*unused*/) noexcept; #endif From e1f8d44397841ca823f282acc9bbae7b6b33d54a Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Mon, 16 Dec 2024 15:50:36 +0100 Subject: [PATCH 30/31] test function selection --- include/firestarter/FunctionSelection.hpp | 23 +- .../firestarter/Platform/PlatformConfig.hpp | 1 - src/firestarter/FunctionSelection.cpp | 42 +- test/UnitTests/CMakeLists.txt | 1 + test/UnitTests/FunctionSelectionTest.cpp | 447 ++++++++++++++++++ 5 files changed, 485 insertions(+), 29 deletions(-) create mode 100644 test/UnitTests/FunctionSelectionTest.cpp diff --git a/include/firestarter/FunctionSelection.hpp b/include/firestarter/FunctionSelection.hpp index eacc1003..55a38bec 100644 --- a/include/firestarter/FunctionSelection.hpp +++ b/include/firestarter/FunctionSelection.hpp @@ -49,18 +49,25 @@ class FunctionSelection { /// Select a PlatformConfig based on its generated id. This function will throw if a payload is not available or the /// id is incorrect. /// \arg FunctionId The id of the PlatformConfig that should be selected. - /// \arg ProcessorInfos Information about the processor which is specific to the current ISA. - /// \arg Topology The topology which contains information about the cpu requied to select the correct function. + /// \arg Features The CPU features of the current processor. + /// \arg InstructionCacheSize The optional size of the instruction cache. /// \arg AllowUnavailablePayload If true we will not throw if the PlatformConfig is not available. - [[nodiscard]] auto selectAvailableFunction(unsigned FunctionId, const ProcessorInformation& ProcessorInfos, - const CPUTopology& Topology, bool AllowUnavailablePayload) const + [[nodiscard]] auto selectAvailableFunction(unsigned FunctionId, const CpuFeatures& Features, + std::optional InstructionCacheSize, + bool AllowUnavailablePayload) const -> std::unique_ptr; /// Select the fallback PlatformConfig if no id is given. - /// \arg ProcessorInfos Information about the processor which is specific to the current ISA. - /// \arg Topology The topology which contains information about the cpu requied to select the correct function. - [[nodiscard]] auto selectDefaultOrFallbackFunction(const ProcessorInformation& ProcessorInfos, - const CPUTopology& Topology) const + /// \arg Model The class that identifies the cpu model. + /// \arg Features The CPU features of the current processor. + /// \arg VendorString The string of the cpu vendor. + /// \arg ModelString The string of the cpu model. + /// \arg InstructionCacheSize The optional size of the instruction cache. + /// \arg NumThreadsPerCore The number of threads per core. + [[nodiscard]] auto selectDefaultOrFallbackFunction(const CpuModel& Model, const CpuFeatures& Features, + const std::string& VendorString, const std::string& ModelString, + std::optional InstructionCacheSize, + unsigned NumThreadsPerCore) const -> std::unique_ptr; /// Print a list of available high-load function and if they are available on the current system. diff --git a/include/firestarter/Platform/PlatformConfig.hpp b/include/firestarter/Platform/PlatformConfig.hpp index 19c3d21d..b83034ce 100644 --- a/include/firestarter/Platform/PlatformConfig.hpp +++ b/include/firestarter/Platform/PlatformConfig.hpp @@ -25,7 +25,6 @@ #include "firestarter/CpuModel.hpp" #include "firestarter/Logging/Log.hpp" #include "firestarter/Payload/Payload.hpp" -#include "firestarter/ProcessorInformation.hpp" #include #include diff --git a/src/firestarter/FunctionSelection.cpp b/src/firestarter/FunctionSelection.cpp index 953d475c..755165d0 100644 --- a/src/firestarter/FunctionSelection.cpp +++ b/src/firestarter/FunctionSelection.cpp @@ -29,17 +29,17 @@ namespace firestarter { -auto FunctionSelection::selectAvailableFunction(unsigned FunctionId, const ProcessorInformation& ProcessorInfos, - const CPUTopology& Topology, bool AllowUnavailablePayload) const +auto FunctionSelection::selectAvailableFunction(unsigned FunctionId, const CpuFeatures& Features, + std::optional InstructionCacheSize, + bool AllowUnavailablePayload) const -> std::unique_ptr { unsigned Id = 1; std::optional DefaultPayloadName; - const auto ProcessorICacheSize = Topology.instructionCacheSize(); for (const auto& Platform : platform::PlatformConfigAndThreads::fromPlatformConfigs(platformConfigs())) { // the selected function if (Id == FunctionId) { - if (!Platform.Config->payload()->isAvailable(ProcessorInfos.cpuFeatures())) { + if (!Platform.Config->payload()->isAvailable(Features)) { const auto ErrorString = "Function " + std::to_string(FunctionId) + " (\"" + Platform.Config->functionName(Platform.ThreadCount) + "\") requires " + Platform.Config->payload()->name() + ", which is not supported by the processor."; @@ -50,7 +50,7 @@ auto FunctionSelection::selectAvailableFunction(unsigned FunctionId, const Proce } } // found function - return Platform.Config->cloneConcreate(ProcessorICacheSize, Platform.ThreadCount); + return Platform.Config->cloneConcreate(InstructionCacheSize, Platform.ThreadCount); } Id++; } @@ -58,18 +58,18 @@ auto FunctionSelection::selectAvailableFunction(unsigned FunctionId, const Proce throw std::invalid_argument("unknown function id: " + std::to_string(FunctionId) + ", see --avail for available ids"); } -auto FunctionSelection::selectDefaultOrFallbackFunction(const ProcessorInformation& ProcessorInfos, - const CPUTopology& Topology) const +auto FunctionSelection::selectDefaultOrFallbackFunction(const CpuModel& Model, const CpuFeatures& Features, + const std::string& VendorString, const std::string& ModelString, + std::optional InstructionCacheSize, + unsigned NumThreadsPerCore) const -> std::unique_ptr { std::optional DefaultPayloadName; - const auto ProcessorICacheSize = Topology.instructionCacheSize(); - const auto ProcessorThreadsPerCore = Topology.homogenousResourceCount().NumThreadsPerCore; for (const auto& Platform : platform::PlatformConfigAndThreads::fromPlatformConfigs(platformConfigs())) { // default function - if (Platform.Config->isDefault(ProcessorInfos.cpuModel(), ProcessorInfos.cpuFeatures())) { - if (Platform.ThreadCount == ProcessorThreadsPerCore) { - return Platform.Config->cloneConcreate(ProcessorICacheSize, Platform.ThreadCount); + if (Platform.Config->isDefault(Model, Features)) { + if (Platform.ThreadCount == NumThreadsPerCore) { + return Platform.Config->cloneConcreate(InstructionCacheSize, Platform.ThreadCount); } DefaultPayloadName = Platform.Config->payload()->name(); } @@ -80,23 +80,22 @@ auto FunctionSelection::selectDefaultOrFallbackFunction(const ProcessorInformati if (DefaultPayloadName) { // default payload available, but number of threads per core is not // supported - log::warn() << "No " << *DefaultPayloadName << " code path for " << ProcessorThreadsPerCore << " threads per core!"; + log::warn() << "No " << *DefaultPayloadName << " code path for " << NumThreadsPerCore << " threads per core!"; } - log::warn() << ProcessorInfos.vendor() << " " << ProcessorInfos.model() - << " is not supported by this version of FIRESTARTER!\n" + log::warn() << VendorString << " " << ModelString << " is not supported by this version of FIRESTARTER!\n" << "Check project website for updates."; // loop over available implementation and check if they are marked as // fallback for (const auto& FallbackPlatformConfigPtr : fallbackPlatformConfigs()) { - if (FallbackPlatformConfigPtr->payload()->isAvailable(ProcessorInfos.cpuFeatures())) { + if (FallbackPlatformConfigPtr->payload()->isAvailable(Features)) { unsigned SelectedThreadsPerCore{}; // find the fallback implementation with the correct thread per core count or select the first available thread // per core count { const auto& Threads = FallbackPlatformConfigPtr->constRef().settings().threads(); - const auto& ThreadIt = std::find(Threads.cbegin(), Threads.cend(), ProcessorThreadsPerCore); + const auto& ThreadIt = std::find(Threads.cbegin(), Threads.cend(), NumThreadsPerCore); if (ThreadIt == Threads.cend()) { SelectedThreadsPerCore = Threads.front(); } else { @@ -108,7 +107,7 @@ auto FunctionSelection::selectDefaultOrFallbackFunction(const ProcessorInformati << " as fallback.\n" << "You can use the parameter --function to try other " "functions."; - return FallbackPlatformConfigPtr->cloneConcreate(ProcessorICacheSize, SelectedThreadsPerCore); + return FallbackPlatformConfigPtr->cloneConcreate(InstructionCacheSize, SelectedThreadsPerCore); } } @@ -121,9 +120,12 @@ auto FunctionSelection::selectFunction(std::optional FunctionId, const const CPUTopology& Topology, bool AllowUnavailablePayload) const -> std::unique_ptr { if (FunctionId) { - return selectAvailableFunction(*FunctionId, ProcessorInfos, Topology, AllowUnavailablePayload); + return selectAvailableFunction(*FunctionId, ProcessorInfos.cpuFeatures(), Topology.instructionCacheSize(), + AllowUnavailablePayload); } - return selectDefaultOrFallbackFunction(ProcessorInfos, Topology); + return selectDefaultOrFallbackFunction( + ProcessorInfos.cpuModel(), ProcessorInfos.cpuFeatures(), ProcessorInfos.vendor(), ProcessorInfos.model(), + Topology.instructionCacheSize(), Topology.homogenousResourceCount().NumThreadsPerCore); } void FunctionSelection::printFunctionSummary(const ProcessorInformation& ProcessorInfos, bool ForceYes) const { diff --git a/test/UnitTests/CMakeLists.txt b/test/UnitTests/CMakeLists.txt index 738a8988..620f16db 100644 --- a/test/UnitTests/CMakeLists.txt +++ b/test/UnitTests/CMakeLists.txt @@ -1,5 +1,6 @@ add_executable(UnitTests CpuBindTest.cpp + FunctionSelectionTest.cpp InstructionGroupsTest.cpp X86CpuFeaturesTest.cpp X86CpuModelTest.cpp diff --git a/test/UnitTests/FunctionSelectionTest.cpp b/test/UnitTests/FunctionSelectionTest.cpp new file mode 100644 index 00000000..9c66e704 --- /dev/null +++ b/test/UnitTests/FunctionSelectionTest.cpp @@ -0,0 +1,447 @@ +/****************************************************************************** + * FIRESTARTER - A Processor Stress Test Utility + * Copyright (C) 2024 TU Dresden, Center for Information Services and High + * Performance Computing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Contact: daniel.hackenberg@tu-dresden.de + *****************************************************************************/ + +#include "firestarter/FunctionSelection.hpp" + +#include + +namespace { + +class FakeCpuFeatures : public firestarter::CpuFeatures { + [[nodiscard]] auto hasAll(const CpuFeatures& /*Features*/) const -> bool override { return true; }; +}; + +class FakeCpuModel : public firestarter::CpuModel { + [[nodiscard]] auto operator<(const CpuModel& /*Other*/) const -> bool override { return true; } + + [[nodiscard]] auto operator==(const CpuModel& /*Other*/) const -> bool override { return true; } +}; + +template class FakePayload : public firestarter::payload::Payload { +public: + FakePayload() + : firestarter::payload::Payload( + /*Name=*/"AvailablePayload", /*RegisterSize=*/0, /*RegisterCount=*/0) {} + + void init(double* /*MemoryAddr*/, uint64_t /*BufferSize*/) const override {} + + void lowLoadFunction(volatile firestarter::LoadThreadWorkType& /*LoadVar*/, + std::chrono::microseconds /*Period*/) const override {} + + [[nodiscard]] auto isAvailable(const firestarter::CpuFeatures& /*Features*/) const -> bool override { + return PayloadIsAvailable; + } + + [[nodiscard]] auto compilePayload(const firestarter::payload::PayloadSettings& /*Settings*/, + bool + /*DumpRegisters*/, + bool /*ErrorDetection*/, bool /*PrintAssembler*/) const + -> firestarter::payload::CompiledPayload::UniquePtr override { + return {nullptr, nullptr}; + } + + [[nodiscard]] auto getAvailableInstructions() const -> std::list override { return {}; } +}; + +constexpr const unsigned ThreadCount1 = 1; +constexpr const unsigned ThreadCount2 = 2; +constexpr const unsigned InvalidThreadCount = 3; + +template +class FakePlatfromConfig : public firestarter::platform::PlatformConfig { +private: + unsigned Id; + +public: + explicit FakePlatfromConfig(unsigned Id) + : firestarter::platform::PlatformConfig( + /*Name=*/"PlatfromConfigTest", + /*Settings=*/ + firestarter::payload::PayloadSettings( + /*Threads=*/{ThreadCount1, ThreadCount2}, /*DataCacheBufferSize=*/{}, /*RamBufferSize=*/0, + /*Lines=*/0, + /*Groups=*/firestarter::InstructionGroups(firestarter::InstructionGroups::InternalType())), + /*Payload=*/std::make_shared>()) + , Id(Id) {} + + [[nodiscard]] auto getId() const -> auto{ return Id; } + +private: + [[nodiscard]] auto isDefault(const firestarter::CpuModel& /*Model*/, + const firestarter::CpuFeatures& /*Features*/) const -> bool override { + return IsDefault; + } + + [[nodiscard]] auto clone() const -> std::unique_ptr override { return nullptr; } + + [[nodiscard]] auto cloneConcreate(std::optional InstructionCacheSize, unsigned ThreadsPerCore) const + -> std::unique_ptr override { + auto Config = std::make_unique>(Id); + Config->settings().concretize(InstructionCacheSize, ThreadsPerCore); + return Config; + } +}; + +constexpr const unsigned PayloadId1 = 4; +constexpr const unsigned PayloadId2 = 5; + +constexpr const std::optional InstructionCacheSize = 6; + +template +class FunctionSelectionTest : public firestarter::FunctionSelection { + std::vector> PlatformConfigs; + std::vector> FallbackPlatformConfigs; + +public: + FunctionSelectionTest() { + if constexpr (WithPlatformConfigs) { + PlatformConfigs = { + std::make_shared>(PayloadId1), + std::make_shared>(PayloadId2)}; + } + if constexpr (WithFallbackPlatformConfigs) { + FallbackPlatformConfigs = { + std::make_shared>(PayloadId1), + std::make_shared>(PayloadId2)}; + } + } + + [[nodiscard]] auto selectAvailableFunction(unsigned FunctionId, std::optional InstructionCacheSize, + bool AllowUnavailablePayload) const + -> std::unique_ptr { + return firestarter::FunctionSelection::selectAvailableFunction(FunctionId, FakeCpuFeatures(), InstructionCacheSize, + AllowUnavailablePayload); + } + + [[nodiscard]] auto selectDefaultOrFallbackFunction(std::optional InstructionCacheSize, + unsigned NumThreadsPerCore) const + -> std::unique_ptr { + return firestarter::FunctionSelection::selectDefaultOrFallbackFunction( + FakeCpuModel(), FakeCpuFeatures(), "VendorString", "ModelString", InstructionCacheSize, NumThreadsPerCore); + } + + [[nodiscard]] auto platformConfigs() const + -> const std::vector>& override { + return PlatformConfigs; + } + + [[nodiscard]] auto fallbackPlatformConfigs() const + -> const std::vector>& override { + return FallbackPlatformConfigs; + } +}; + +template +using FunctionSelectionWithPlatformConfigsTest = + FunctionSelectionTest; + +template +using FunctionSelectionWithFallbackPlatformConfigsTest = + FunctionSelectionTest; + +template +void checkSelectAvailableFunctionThrowWithPlatformConfigs(const unsigned FunctionId, + const std::optional InstructionCacheSize, + const bool AllowUnavailablePayload) { + EXPECT_ANY_THROW((void)(FunctionSelectionWithPlatformConfigsTest() + .selectAvailableFunction( + /*FunctionId=*/FunctionId, InstructionCacheSize, AllowUnavailablePayload))); +} + +/// Check that the function with the given id selects the correct available payload, thread count and instruction cache +/// size. +template +void checkSelectAvailableFunctionNoThrowWithPlatformConfigs(const unsigned FunctionId, const unsigned PayloadId, + const unsigned ThreadCount, + const std::optional InstructionCacheSize, + const bool AllowUnavailablePayload) { + std::unique_ptr Config; + + EXPECT_NO_THROW(Config = + (FunctionSelectionWithPlatformConfigsTest() + .selectAvailableFunction(FunctionId, InstructionCacheSize, AllowUnavailablePayload))); + + const auto* FakeConfg = dynamic_cast*>(Config.get()); + // Id describes the nth element in the list of platform configs. + EXPECT_EQ(FakeConfg->getId(), PayloadId); + EXPECT_EQ(FakeConfg->settings().thread(), ThreadCount); + EXPECT_EQ(FakeConfg->settings().instructionCacheSize(), InstructionCacheSize); +} + +/// Check that the correct fallback function is selected +template +void checkSelectDefaultOrFallbackFunctionNoThrowWithFallbackPlatformConfigs( + const unsigned PayloadId, const unsigned InputThreadCount, const unsigned OutputThreadCount, + const std::optional InstructionCacheSize) { + std::unique_ptr Config; + EXPECT_NO_THROW( + Config = (FunctionSelectionWithFallbackPlatformConfigsTest() + .selectDefaultOrFallbackFunction(InstructionCacheSize, + /*NumThreadsPerCore=*/InputThreadCount))); + { + const auto* FakeConfg = dynamic_cast*>(Config.get()); + // Id describes the nth element in the list of platform configs. + EXPECT_EQ(FakeConfg->getId(), PayloadId); + EXPECT_EQ(FakeConfg->settings().thread(), OutputThreadCount); + EXPECT_EQ(FakeConfg->settings().instructionCacheSize(), InstructionCacheSize); + } +} + +/// Check that the default fallback function is selected +template +void checkSelectDefaultOrFallbackFunctionNoThrowWithPlatformConfigs( + const unsigned PayloadId, const unsigned ThreadCount, const std::optional InstructionCacheSize) { + std::unique_ptr Config; + EXPECT_NO_THROW( + Config = + (FunctionSelectionWithPlatformConfigsTest() + .selectDefaultOrFallbackFunction(InstructionCacheSize, + /*NumThreadsPerCore=*/ThreadCount))); + { + const auto* FakeConfg = dynamic_cast*>(Config.get()); + // Id describes the nth element in the list of platform configs. + EXPECT_EQ(FakeConfg->getId(), PayloadId); + EXPECT_EQ(FakeConfg->settings().thread(), ThreadCount); + EXPECT_EQ(FakeConfg->settings().instructionCacheSize(), InstructionCacheSize); + } +} + +template +void checkSelectDefaultOrFallbackFunctionThrowWithPlatformConfigs(const unsigned ThreadCount, + const std::optional InstructionCacheSize) { + EXPECT_ANY_THROW((void)(FunctionSelectionWithPlatformConfigsTest() + .selectDefaultOrFallbackFunction(InstructionCacheSize, + /*NumThreadsPerCore=*/ThreadCount))); +} + +} // namespace + +TEST(FunctionSelectionTest, CheckInvalidFunctionIds) { + // Id 0 is not valid. + checkSelectAvailableFunctionThrowWithPlatformConfigs( + /*FunctionId=*/0, InstructionCacheSize, + /*AllowUnavailablePayload=*/true); + checkSelectAvailableFunctionThrowWithPlatformConfigs( + /*FunctionId=*/0, InstructionCacheSize, + /*AllowUnavailablePayload=*/false); + + checkSelectAvailableFunctionThrowWithPlatformConfigs( + /*FunctionId=*/0, InstructionCacheSize, + /*AllowUnavailablePayload=*/true); + checkSelectAvailableFunctionThrowWithPlatformConfigs( + /*FunctionId=*/0, InstructionCacheSize, + /*AllowUnavailablePayload=*/false); + + // Id is too big. + checkSelectAvailableFunctionThrowWithPlatformConfigs( + /*FunctionId=*/5, InstructionCacheSize, + /*AllowUnavailablePayload=*/true); + checkSelectAvailableFunctionThrowWithPlatformConfigs( + /*FunctionId=*/5, InstructionCacheSize, + /*AllowUnavailablePayload=*/false); + + checkSelectAvailableFunctionThrowWithPlatformConfigs( + /*FunctionId=*/5, InstructionCacheSize, + /*AllowUnavailablePayload=*/true); + checkSelectAvailableFunctionThrowWithPlatformConfigs( + /*FunctionId=*/5, InstructionCacheSize, + /*AllowUnavailablePayload=*/false); +} + +TEST(FunctionSelectionTest, CheckFunctionIds) { + // Ids starting from 1 are valid + checkSelectAvailableFunctionNoThrowWithPlatformConfigs( + 1, PayloadId1, ThreadCount1, InstructionCacheSize, /*AllowUnavailablePayload=*/false); + checkSelectAvailableFunctionNoThrowWithPlatformConfigs( + 1, PayloadId1, ThreadCount1, InstructionCacheSize, /*AllowUnavailablePayload=*/true); + + checkSelectAvailableFunctionThrowWithPlatformConfigs( + 1, InstructionCacheSize, /*AllowUnavailablePayload=*/false); + checkSelectAvailableFunctionNoThrowWithPlatformConfigs( + 1, PayloadId1, ThreadCount1, InstructionCacheSize, /*AllowUnavailablePayload=*/true); + + checkSelectAvailableFunctionNoThrowWithPlatformConfigs( + 2, PayloadId1, ThreadCount2, InstructionCacheSize, /*AllowUnavailablePayload=*/false); + checkSelectAvailableFunctionNoThrowWithPlatformConfigs( + 2, PayloadId1, ThreadCount2, InstructionCacheSize, /*AllowUnavailablePayload=*/true); + + checkSelectAvailableFunctionThrowWithPlatformConfigs( + 2, InstructionCacheSize, /*AllowUnavailablePayload=*/false); + checkSelectAvailableFunctionNoThrowWithPlatformConfigs( + 2, PayloadId1, ThreadCount2, InstructionCacheSize, /*AllowUnavailablePayload=*/true); + + checkSelectAvailableFunctionNoThrowWithPlatformConfigs( + 3, PayloadId2, ThreadCount1, InstructionCacheSize, /*AllowUnavailablePayload=*/false); + checkSelectAvailableFunctionNoThrowWithPlatformConfigs( + 3, PayloadId2, ThreadCount1, InstructionCacheSize, /*AllowUnavailablePayload=*/true); + + checkSelectAvailableFunctionThrowWithPlatformConfigs( + 3, InstructionCacheSize, /*AllowUnavailablePayload=*/false); + checkSelectAvailableFunctionNoThrowWithPlatformConfigs( + 3, PayloadId2, ThreadCount1, InstructionCacheSize, /*AllowUnavailablePayload=*/true); + + checkSelectAvailableFunctionNoThrowWithPlatformConfigs( + 4, PayloadId2, ThreadCount2, InstructionCacheSize, /*AllowUnavailablePayload=*/false); + checkSelectAvailableFunctionNoThrowWithPlatformConfigs( + 4, PayloadId2, ThreadCount2, InstructionCacheSize, /*AllowUnavailablePayload=*/true); + + checkSelectAvailableFunctionThrowWithPlatformConfigs( + 4, InstructionCacheSize, /*AllowUnavailablePayload=*/false); + checkSelectAvailableFunctionNoThrowWithPlatformConfigs( + 4, PayloadId2, ThreadCount2, InstructionCacheSize, /*AllowUnavailablePayload=*/true); +} + +TEST(FunctionSelectionTest, NoFallbackFound) { + EXPECT_ANY_THROW((void)(FunctionSelectionWithFallbackPlatformConfigsTest() + .selectDefaultOrFallbackFunction( + /*InstructionCacheSize=*/{}, + /*NumThreadsPerCore=*/1))); +} + +TEST(FunctionSelectionTest, CheckFallbackThreadCount) { + checkSelectDefaultOrFallbackFunctionNoThrowWithFallbackPlatformConfigs( + PayloadId1, /*InputThreadCount=*/ThreadCount1, /*OutputThreadCount=*/ThreadCount1, InstructionCacheSize); + checkSelectDefaultOrFallbackFunctionNoThrowWithFallbackPlatformConfigs( + PayloadId1, /*InputThreadCount=*/ThreadCount1, /*OutputThreadCount=*/ThreadCount1, InstructionCacheSize); + + checkSelectDefaultOrFallbackFunctionNoThrowWithFallbackPlatformConfigs( + PayloadId1, /*InputThreadCount=*/ThreadCount2, /*OutputThreadCount=*/ThreadCount2, InstructionCacheSize); + checkSelectDefaultOrFallbackFunctionNoThrowWithFallbackPlatformConfigs( + PayloadId1, /*InputThreadCount=*/ThreadCount2, /*OutputThreadCount=*/ThreadCount2, InstructionCacheSize); + + checkSelectDefaultOrFallbackFunctionNoThrowWithFallbackPlatformConfigs( + PayloadId1, /*InputThreadCount=*/InvalidThreadCount, /*OutputThreadCount=*/ThreadCount1, InstructionCacheSize); + checkSelectDefaultOrFallbackFunctionNoThrowWithFallbackPlatformConfigs( + PayloadId1, /*InputThreadCount=*/InvalidThreadCount, /*OutputThreadCount=*/ThreadCount1, InstructionCacheSize); + + checkSelectDefaultOrFallbackFunctionNoThrowWithFallbackPlatformConfigs( + PayloadId2, /*InputThreadCount=*/ThreadCount1, /*OutputThreadCount=*/ThreadCount1, InstructionCacheSize); + + checkSelectDefaultOrFallbackFunctionNoThrowWithFallbackPlatformConfigs( + PayloadId2, /*InputThreadCount=*/ThreadCount2, /*OutputThreadCount=*/ThreadCount2, InstructionCacheSize); + + checkSelectDefaultOrFallbackFunctionNoThrowWithFallbackPlatformConfigs( + PayloadId2, /*InputThreadCount=*/InvalidThreadCount, /*OutputThreadCount=*/ThreadCount1, InstructionCacheSize); +} + +TEST(FunctionSelectionTest, NoDefaultFound) { + // non of the configs are the default, no fallbacks available -> throw + checkSelectDefaultOrFallbackFunctionThrowWithPlatformConfigs(ThreadCount1, + InstructionCacheSize); + checkSelectDefaultOrFallbackFunctionThrowWithPlatformConfigs(ThreadCount2, + InstructionCacheSize); + checkSelectDefaultOrFallbackFunctionThrowWithPlatformConfigs(InvalidThreadCount, + InstructionCacheSize); +} + +TEST(FunctionSelectionTest, DefaultThreadCountFound) { + // default config with correct thread count found -> no throw + checkSelectDefaultOrFallbackFunctionNoThrowWithPlatformConfigs( + PayloadId1, ThreadCount1, InstructionCacheSize); + checkSelectDefaultOrFallbackFunctionNoThrowWithPlatformConfigs( + PayloadId1, ThreadCount2, InstructionCacheSize); + + checkSelectDefaultOrFallbackFunctionNoThrowWithPlatformConfigs( + PayloadId1, ThreadCount1, InstructionCacheSize); + checkSelectDefaultOrFallbackFunctionNoThrowWithPlatformConfigs( + PayloadId1, ThreadCount2, InstructionCacheSize); + + checkSelectDefaultOrFallbackFunctionNoThrowWithPlatformConfigs( + PayloadId2, ThreadCount1, InstructionCacheSize); + checkSelectDefaultOrFallbackFunctionNoThrowWithPlatformConfigs( + PayloadId2, ThreadCount2, InstructionCacheSize); +} + +TEST(FunctionSelectionTest, DefaultThreadCountNotFound) { + // default config found but not the correct number of thread, no fallbacks available -> throw + checkSelectDefaultOrFallbackFunctionThrowWithPlatformConfigs(InvalidThreadCount, + InstructionCacheSize); + checkSelectDefaultOrFallbackFunctionThrowWithPlatformConfigs(InvalidThreadCount, + InstructionCacheSize); + checkSelectDefaultOrFallbackFunctionThrowWithPlatformConfigs(InvalidThreadCount, + InstructionCacheSize); +} \ No newline at end of file From 1101ea5a6de6181bec75089334edb7a76de7d1fc Mon Sep 17 00:00:00 2001 From: Markus Schmidl Date: Mon, 16 Dec 2024 18:57:52 +0100 Subject: [PATCH 31/31] fix windows test build --- test/UnitTests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/UnitTests/CMakeLists.txt b/test/UnitTests/CMakeLists.txt index 620f16db..e54ae21d 100644 --- a/test/UnitTests/CMakeLists.txt +++ b/test/UnitTests/CMakeLists.txt @@ -14,4 +14,4 @@ target_link_libraries(UnitTests ) include(GoogleTest) -gtest_discover_tests(UnitTests) \ No newline at end of file +gtest_discover_tests(UnitTests DISCOVERY_MODE PRE_TEST) \ No newline at end of file