Skip to content

Commit

Permalink
Make it work, update callers, log it
Browse files Browse the repository at this point in the history
  • Loading branch information
eggrobin committed Mar 30, 2024
1 parent 3fdc292 commit 36c3c71
Show file tree
Hide file tree
Showing 10 changed files with 47 additions and 30 deletions.
5 changes: 3 additions & 2 deletions base/cpuid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace _cpuid {
namespace internal {
namespace {

std::vector<CPUIDFeatureFlag const&> CPUIDFlags;
std::vector<CPUIDFeatureFlag> CPUIDFlags;

Check warning on line 21 in base/cpuid.cpp

View workflow job for this annotation

GitHub Actions / check-cpp

build/include_what_you_use

Add #include <vector> for vector<>

CPUIDResult CPUID(std::uint32_t const eax, std::uint32_t const ecx) {
#if PRINCIPIA_COMPILER_MSVC
Expand Down Expand Up @@ -78,7 +78,7 @@ std::string ProcessorBrandString() {
}

std::string CPUFeatures() {
std::string result = "";
std::string result;
for (auto const& flag : CPUIDFlags) {
if (flag.IsSet()) {
if (!result.empty()) {
Expand All @@ -87,6 +87,7 @@ std::string CPUFeatures() {
result += flag.name();
}
}
return result;
}

} // namespace internal
Expand Down
30 changes: 16 additions & 14 deletions base/cpuid.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,28 +56,30 @@ std::string CPUFeatures();
namespace cpuid_feature_flags {
// Table 3-11.
PRINCIPIA_CPUID_FLAG(FPU, 0x01, EDX, 0); // x87 Floating Point Unit on chip.
PRINCIPIA_CPUID_FLAG(PSN, 0x01, EDX, 18); // Processor Serial Number.
PRINCIPIA_CPUID_FLAG(SSE, 0x01, EDX, 25); // Streaming SIMD Extensions.
PRINCIPIA_CPUID_FLAG(SSE2, 0x01, EDX, 26); // Streaming SIMD Extensions 2.
PRINCIPIA_CPUID_FLAG(SSE3, 0x01, ECX, 0); // Streaming SIMD Extensions 3.
PRINCIPIA_CPUID_FLAG(FMA, 0x01, ECX, 12); // Fused Multiply Add.

PRINCIPIA_CPUID_FLAG(PSN, 0x01, EDX, 18); // Processor Serial Number.
PRINCIPIA_CPUID_FLAG(SSE, 0x01, EDX, 25); // Streaming SIMD Extensions.
PRINCIPIA_CPUID_FLAG(SSE2, 0x01, EDX, 26); // Streaming SIMD Extensions 2.
PRINCIPIA_CPUID_FLAG(SSE3, 0x01, ECX, 0); // Streaming SIMD Extensions 3.
PRINCIPIA_CPUID_FLAG(FMA, 0x01, ECX, 12); // Fused Multiply Add.
PRINCIPIA_CPUID_FLAG(SSE4_1, 0x01, ECX, 19); // Streaming SIMD Extensions 4.1.
PRINCIPIA_CPUID_FLAG(AVX, 0x01, ECX, 28); // Advanced Vector eXtensions.
// Table 3-8.

// Table 3-8, Structured Extended Feature Flags Enumeration Leaf.
PRINCIPIA_CPUID_FLAG(AVX2, 0x07, EBX, 5); // Advanced Vector eXtensions 2.
PRINCIPIA_CPUID_FLAG(AVX512F, 0x07, EBX, 16); // AVX-512 Foundation.
PRINCIPIA_CPUID_FLAG(AVX512DQ, 0x07, EBX, 17); // AVX-512 .
PRINCIPIA_CPUID_FLAG(AVX512_IFMA, 0x07, EBX, 21); // AVX-512 .
PRINCIPIA_CPUID_FLAG(AVX512PF, 0x07, EBX, 26); // AVX-512 .
PRINCIPIA_CPUID_FLAG(AVX512ER, 0x07, EBX, 27); // AVX-512 .
PRINCIPIA_CPUID_FLAG(AVX512CD, 0x07, EBX, 28); // AVX-512 .
PRINCIPIA_CPUID_FLAG(AVX512BW, 0x07, EBX, 30); // AVX-512 .
PRINCIPIA_CPUID_FLAG(AVX512VL, 0x07, EBX, 31); // AVX-512 .
PRINCIPIA_CPUID_FLAG(AVX512DQ, 0x07, EBX, 17); // DWORD and QWORD instructions.
PRINCIPIA_CPUID_FLAG(AVX512VL, 0x07, EBX, 31); // Vector Length Extensions.
PRINCIPIA_CPUID_FLAG(AVX512_FP16, 0x07, ECX, 23); // IEEE-754 binary16.
} // namespace cpuid_feature_flags
} // namespace internal

#undef PRINCIPIA_CPUID_FLAG

using internal::CPUFeatures;
using internal::CPUVendorIdentificationString;
namespace cpuid_feature_flags = internal::cpuid_feature_flags
using internal::ProcessorBrandString;
namespace cpuid_feature_flags = internal::cpuid_feature_flags;

} // namespace _cpuid
} // namespace base
Expand Down
9 changes: 9 additions & 0 deletions base/cpuid_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ namespace principia {
namespace base {

using ::testing::AnyOf;
using ::testing::HasSubstr;
using ::testing::Not;
using ::testing::Test;
using namespace principia::base::_cpuid;

Expand All @@ -20,6 +22,10 @@ TEST_F(CPUIDTest, Vendor) {
AnyOf("AuthenticAMD", "GenuineIntel"));
}

TEST_F(CPUIDTest, Brand) {
EXPECT_THAT(ProcessorBrandString(), AnyOf(HasSubstr("Intel(R) Xeon(R)")));
}

TEST_F(CPUIDTest, CPUFeatureFlags) {
// We require Prescott or later.
EXPECT_TRUE(cpuid_feature_flags::FPU.IsSet());
Expand All @@ -30,6 +36,9 @@ TEST_F(CPUIDTest, CPUFeatureFlags) {
// We are not running these tests on a Pentium III, so we do not have the
// Processor Serial Number feature.
EXPECT_FALSE(cpuid_feature_flags::PSN.IsSet());
EXPECT_THAT(
CPUFeatures(),
AllOf(HasSubstr("FPU"), HasSubstr("SSE2"), Not(HasSubstr("PSN"))));
}

} // namespace base
Expand Down
6 changes: 3 additions & 3 deletions geometry/grassmann_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class GrassmannTest : public testing::Test {
using GrassmannDeathTest = GrassmannTest;

TEST_F(GrassmannTest, VectorFMA) {
if (!CanEmitFMAInstructions || !HasCPUFeatures(CPUFeatureFlags::FMA)) {
if (!CanEmitFMAInstructions || !cpuid_feature_flags::FPU.IsSet()) {
GTEST_SKIP() << "Cannot test FMA on a machine without FMA";
}
Length const a = a_.x;
Expand All @@ -101,7 +101,7 @@ TEST_F(GrassmannTest, VectorFMA) {
}

TEST_F(GrassmannTest, BivectorFMA) {
if (!CanEmitFMAInstructions || !HasCPUFeatures(CPUFeatureFlags::FMA)) {
if (!CanEmitFMAInstructions || !cpuid_feature_flags::FPU.IsSet()) {
GTEST_SKIP() << "Cannot test FMA on a machine without FMA";
}
Length const a = a_.x;
Expand All @@ -120,7 +120,7 @@ TEST_F(GrassmannTest, BivectorFMA) {
}

TEST_F(GrassmannTest, TrivectorFMA) {
if (!CanEmitFMAInstructions || !HasCPUFeatures(CPUFeatureFlags::FMA)) {
if (!CanEmitFMAInstructions || !cpuid_feature_flags::FPU.IsSet()) {
GTEST_SKIP() << "Cannot test FMA on a machine without FMA";
}
Length const a = a_.x;
Expand Down
2 changes: 1 addition & 1 deletion geometry/point_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class PointTest : public testing::Test {
using PointDeathTest = PointTest;

TEST_F(PointTest, FMA) {
if (!CanEmitFMAInstructions || !HasCPUFeatures(CPUFeatureFlags::FMA)) {
if (!CanEmitFMAInstructions || !cpuid_feature_flags::FPU.IsSet()) {
GTEST_SKIP() << "Cannot test FMA on a machine without FMA";
}
EXPECT_THAT(FusedMultiplyAdd(3 * Litre, 5 * Second / Litre, mjd0),
Expand Down
9 changes: 7 additions & 2 deletions ksp_plugin/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "astronomy/time_scales.hpp"
#include "base/array.hpp"
#include "base/base64.hpp"
#include "base/cpuid.hpp"
#include "base/encoder.hpp"
#include "base/fingerprint2011.hpp"
#include "base/flags.hpp"
Expand Down Expand Up @@ -83,6 +84,7 @@ using namespace principia::astronomy::_epoch;
using namespace principia::astronomy::_time_scales;
using namespace principia::base::_array;
using namespace principia::base::_base64;
using namespace principia::base::_cpuid;
using namespace principia::base::_encoder;
using namespace principia::base::_fingerprint2011;
using namespace principia::base::_flags;
Expand Down Expand Up @@ -730,8 +732,11 @@ void __cdecl principia__InitGoogleLogging() {
<< " built on " << BuildDate
<< " by " << principia::base::CompilerName
<< " version " << principia::base::CompilerVersion
<< " for " << principia::base::OperatingSystem
<< " " << principia::base::Architecture;
<< " for " << principia::base::OperatingSystem << " "
<< principia::base::Architecture;
LOG(ERROR) << "Running on " << ProcessorBrandString() << " ("
<< CPUVendorIdentificationString() << ")";
LOG(ERROR) << "with " << CPUFeatures();
#if OS_WIN
MODULEINFO module_info;
memset(&module_info, 0, sizeof(module_info));
Expand Down
10 changes: 5 additions & 5 deletions numerics/cbrt_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class CubeRootTest : public ::testing::Test {
cbrt_y.rounded_to_nearest) {
++method_3²ᴄZ5¹_misroundings;
}
if (CanEmitFMAInstructions && HasCPUFeatures(CPUFeatureFlags::FMA)) {
if (CanEmitFMAInstructions && cpuid_feature_flags::FPU.IsSet()) {
EXPECT_THAT(method_5²Z4¹FMA::Cbrt<Rounding::Faithful>(y),
AnyOf(cbrt_y.rounded_down, cbrt_y.rounded_up));
EXPECT_THAT(method_5²Z4¹FMA::Cbrt<Rounding::Correct>(y),
Expand All @@ -113,7 +113,7 @@ class CubeRootTest : public ::testing::Test {
}
}
EXPECT_THAT(method_3²ᴄZ5¹_misroundings, Eq(expected_3²ᴄZ5¹_misroundings));
if (CanEmitFMAInstructions && HasCPUFeatures(CPUFeatureFlags::FMA)) {
if (CanEmitFMAInstructions && cpuid_feature_flags::FPU.IsSet()) {
EXPECT_THAT(method_5²Z4¹FMA_misroundings,
Eq(expected_5²Z4¹FMA_misroundings));
}
Expand All @@ -140,7 +140,7 @@ TEST_F(CubeRootTest, Rescaling) {
Eq(Cbrt(2)));
EXPECT_THAT(0x1p358 * method_3²ᴄZ5¹::Cbrt<Rounding::Correct>(0x1p-1073),
Eq(Cbrt(2)));
if (CanEmitFMAInstructions && HasCPUFeatures(CPUFeatureFlags::FMA)) {
if (CanEmitFMAInstructions && cpuid_feature_flags::FPU.IsSet()) {
EXPECT_THAT(0x1p-340 * method_5²Z4¹FMA::Cbrt<Rounding::Correct>(0x1p1021),
Eq(Cbrt(2)));
EXPECT_THAT(0x1p341 * method_5²Z4¹FMA::Cbrt<Rounding::Correct>(0x1p-1022),
Expand Down Expand Up @@ -206,7 +206,7 @@ TEST_F(CubeRootTest, BoundsOfTheRescalingRange) {
Eq(0x1p113 * Cbrt(4)));
EXPECT_THAT(method_3²ᴄZ5¹::Cbrt<Rounding::Correct>(0x1.0'0000'0000'0002p341),
Eq(0x1p113 * Cbrt(0x1.0'0000'0000'0002p2)));
if (CanEmitFMAInstructions && HasCPUFeatures(CPUFeatureFlags::FMA)) {
if (CanEmitFMAInstructions && cpuid_feature_flags::FPU.IsSet()) {
EXPECT_THAT(method_5²Z4¹FMA::Cbrt<Rounding::Correct>(0x1p-438),
Eq(0x1p-146));
EXPECT_THAT(
Expand Down Expand Up @@ -237,7 +237,7 @@ TEST_F(CubeRootTest, ParticularlyDifficultRounding) {
Eq(cbrt_y.rounded_to_nearest));
EXPECT_THAT(method_3²ᴄZ5¹::Cbrt<Rounding::Faithful>(y),
AllOf(Ne(cbrt_y.rounded_to_nearest), Eq(cbrt_y.rounded_down)));
if (CanEmitFMAInstructions && HasCPUFeatures(CPUFeatureFlags::FMA)) {
if (CanEmitFMAInstructions && cpuid_feature_flags::FPU.IsSet()) {
EXPECT_THAT(method_5²Z4¹FMA::Cbrt<Rounding::Correct>(y),
Eq(cbrt_y.rounded_to_nearest));
EXPECT_THAT(method_5²Z4¹FMA::Cbrt<Rounding::Faithful>(y),
Expand Down
2 changes: 1 addition & 1 deletion numerics/fma.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ constexpr bool CanEmitFMAInstructions = false;

#if PRINCIPIA_USE_FMA_IF_AVAILABLE()
#define PRINCIPIA_USE_HARDWARE_FMA_DEFAULT \
(CanEmitFMAInstructions && HasCPUFeatures(CPUFeatureFlags::FMA));
(CanEmitFMAInstructions && cpuid_feature_flags::FPU.IsSet());
#else
#define PRINCIPIA_USE_HARDWARE_FMA_DEFAULT false;
#endif
Expand Down
2 changes: 1 addition & 1 deletion numerics/fma_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class FMATest : public testing::Test {
protected:
void SetUp() override {
// Note that we test even if |UseHardwareFMA| is false, i.e., even in debug.
if (!CanEmitFMAInstructions || !HasCPUFeatures(CPUFeatureFlags::FMA)) {
if (!CanEmitFMAInstructions || !cpuid_feature_flags::FPU.IsSet()) {
GTEST_SKIP() << "Cannot test FMA on a machine without FMA";
}
}
Expand Down
2 changes: 1 addition & 1 deletion quantities/elementary_functions_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ using namespace principia::testing_utilities::_vanishes_before;
class ElementaryFunctionsTest : public testing::Test {};

TEST_F(ElementaryFunctionsTest, FMA) {
if (!CanEmitFMAInstructions || !HasCPUFeatures(CPUFeatureFlags::FMA)) {
if (!CanEmitFMAInstructions || !cpuid_feature_flags::FPU.IsSet()) {
GTEST_SKIP() << "Cannot test FMA on a machine without FMA";
}
EXPECT_EQ(11 * Coulomb,
Expand Down

0 comments on commit 36c3c71

Please sign in to comment.