浏览代码

AK: Add `AK::SIMD::exp_approximate`

This approximation tries to generate values within 0.1% of their actual
expected value. Microbenchmarks indicate that this iterative SIMD
version can be up to 60x faster than `AK::SIMD::exp`.
Jelle Raaijmakers 2 年之前
父节点
当前提交
f4342c9118
共有 3 个文件被更改,包括 43 次插入0 次删除
  1. 9 0
      AK/SIMDMath.h
  2. 1 0
      Tests/AK/CMakeLists.txt
  3. 33 0
      Tests/AK/TestSIMD.cpp

+ 9 - 0
AK/SIMDMath.h

@@ -66,6 +66,15 @@ ALWAYS_INLINE static f32x4 exp(f32x4 v)
     };
 }
 
+ALWAYS_INLINE static f32x4 exp_approximate(f32x4 v)
+{
+    static constexpr int number_of_iterations = 10;
+    auto result = 1.f + v / (1 << number_of_iterations);
+    for (int i = 0; i < number_of_iterations; ++i)
+        result *= result;
+    return result;
+}
+
 ALWAYS_INLINE static f32x4 sqrt(f32x4 v)
 {
 #if ARCH(x86_64)

+ 1 - 0
Tests/AK/CMakeLists.txt

@@ -61,6 +61,7 @@ set(AK_TEST_SOURCES
     TestQuickSort.cpp
     TestRedBlackTree.cpp
     TestRefPtr.cpp
+    TestSIMD.cpp
     TestSinglyLinkedList.cpp
     TestSourceGenerator.cpp
     TestSourceLocation.cpp

+ 33 - 0
Tests/AK/TestSIMD.cpp

@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2023, Jelle Raaijmakers <jelle@gmta.nl>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibTest/TestCase.h>
+
+#include <AK/SIMD.h>
+#include <AK/SIMDMath.h>
+
+TEST_CASE(exp)
+{
+    AK::SIMD::f32x4 v = { .2f, .4f, .6f, .8f };
+    auto result = AK::SIMD::exp(v);
+
+    EXPECT_APPROXIMATE(result[0], 1.22140276f);
+    EXPECT_APPROXIMATE(result[1], 1.49182470f);
+    EXPECT_APPROXIMATE(result[2], 1.82211880f);
+    EXPECT_APPROXIMATE(result[3], 2.22554093f);
+}
+
+TEST_CASE(exp_approximate)
+{
+    AK::SIMD::f32x4 v = { .2f, .4f, .6f, .8f };
+    auto result = AK::SIMD::exp_approximate(v);
+    constexpr float accuracy = .001f;
+
+    EXPECT(fabsf(result[0] - 1.22140276f) <= accuracy);
+    EXPECT(fabsf(result[1] - 1.49182470f) <= accuracy);
+    EXPECT(fabsf(result[2] - 1.82211880f) <= accuracy);
+    EXPECT(fabsf(result[3] - 2.22554093f) <= accuracy);
+}