[英]Efficient floating point modulus one in C
我正在尋找一種 CPU 效率非常高的方法來計算 C 中的浮點模數一(包括負值)。 我將它用於歸一化相位減少(包裝,即 7.6 -> 0.6、0.2->0.2、-1.1 -> 0.9 等等)。
據我了解, fmod() 以及 floor() 通常效率很低。 我不需要 function 嚴格,即考慮到 nan 或 inf 因為我負責傳遞有效值。
我一直在使用
m = x - (float)(int)x +(float)(x<0.f);
// branchless form to add one if x was negative
從基准測試中,它通常比 fmod() 或使用 floor() 代替 int 轉換更有效,但我想知道是否存在更有效的方法,可能基於位操作......
我正在使用 gcc 在 64 位英特爾 CPU 上進行編碼,但出於我的目的,我使用的是 32 位單精度浮點數。
如果在其他地方也解決了同樣的問題,我深表歉意,但從我的搜索中我找不到關於這個特定主題的任何信息。
C++ 中的原型(我不是最新的 C),填充邏輯仍未優化,但如果您的系統上有 AVX512,您可以執行類似的操作來處理 8 個雙精度數,或一個循環中的 16 個浮點數。 我在這里發現了很多有用的東西: 內在函數備忘單
我使用了 Visual Studio 2022 中的 MSVC 編譯器
#include <type_traits>
#include <vector>
#include <immintrin.h>
void reduce_phases(std::vector<double>& inputs)
{
static constexpr std::size_t vector_size = 512ul / sizeof(double);
auto number_to_pad = vector_size - (inputs.size() % vector_size);
inputs.insert(inputs.end(), number_to_pad, 0.0);
auto data_ptr = inputs.data();
for (std::size_t n{ 0ul }; n < inputs.size(); n += vector_size, data_ptr += vector_size)
{
auto values = _mm512_load_pd(data_ptr);
auto floors = _mm512_floor_pd(values);
auto result = _mm512_sub_pd(values, floors);
_mm512_store_pd(data_ptr, result);
}
inputs.erase(inputs.end() - number_to_pad, inputs.end());
}
void reduce_phases(std::vector<float>& inputs)
{
static constexpr std::size_t vector_size = 512ul / sizeof(float);
auto number_to_pad = vector_size - (inputs.size() % vector_size);
inputs.insert(inputs.end(), number_to_pad, 0.0);
auto data_ptr = inputs.data();
for (std::size_t n{ 0ul }; n < inputs.size(); n += vector_size, data_ptr += vector_size)
{
auto values = _mm512_load_ps(data_ptr);
auto floors = _mm512_floor_ps(values);
auto result = _mm512_sub_ps(values, floors);
_mm512_store_ps(data_ptr, result);
}
inputs.erase(inputs.end() - number_to_pad, inputs.end());
}
int main()
{
std::vector<double> values{ -1.1, -1.9, -1.5, -0.4, 0.0, 0.4, 1.5, 1.9, 2.1 };
reduce_phases(values);
std::vector<float> float_values{ -1.1f, -1.9f, -1.5f, -0.4f, 0.0f, 0.4f, 1.5f, 1.9f, 2.1f };
reduce_phases(float_values);
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.