SVML __m256d _mm256_log2_pd (__m256d a)在除Intel以外的其他编译器上不可用,他们说它的性能在AMD处理器上受到限制。g ++-4.8中缺少 Internet上AVX日志内在函数(_mm256_log_ps)中引用的某些实现吗?和用于SSE和AVX的SIMD数学库,但是它们似乎比AVX2的SSE更多。还有一个Agner Fog的向量库,但是它是一个大型库,其中包含的内容远远超过了向量log2,因此从实现中很难仅找出向量log2操作的基本部分。
那么有人能解释一下如何有效地log2()对4个double数字的向量进行运算吗?也就是说,它很喜欢__m256d _mm256_log2_pd (__m256d a),但是可用于其他编译器,并且对于AMD和Intel处理器都相当有效。
编辑:在我当前的特定情况下,数字的概率在0到1之间,对数用于熵计算:所有i的和取反P[i]*log(P[i])。的浮点指数范围P[i]很大,因此数字可以接近0。我不确定精度,因此会考虑以30个尾数开头的任何解决方案,尤其是可调整的解决方案是首选。
EDIT2:这是到目前为止我的实现,基于https://en.wikipedia.org/wiki/Logarithm#Power_series的 “更有效的系列” 。如何改善?(同时需要提高性能和准确性)
到目前为止,我的实现每秒可以执行405 268 490次操作,而且直到第8位数字为止似乎都很精确。使用以下功能衡量性能:
#include <chrono>
#include <cmath>
#include <cstdio>
#include <immintrin.h>
// ... Log2() implementation here
const int64_t cnLogs = 100 * 1000 * 1000;
void BenchmarkLog2Vect() {
__m256d sums = _mm256_setzero_pd();
auto start = std::chrono::high_resolution_clock::now();
for (int64_t i = 1; i <= cnLogs; i += 4) {
const __m256d x = _mm256_set_pd(double(i+3), double(i+2), double(i+1), double(i));
const __m256d logs = Log2(x);
sums = _mm256_add_pd(sums, logs);
}
auto elapsed = std::chrono::high_resolution_clock::now() - start;
double nSec = 1e-6 * std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();
double sum = sums.m256d_f64[0] + sums.m256d_f64[1] + sums.m256d_f64[2] + sums.m256d_f64[3];
printf("Vect Log2: %.3lf Ops/sec calculated %.3lf\n", cnLogs / nSec, sum);
}
与C ++和汇编语言中对数的结果相比,当前向量实现的速度是C + +的 4倍std::log2()和2.5倍std::log()。
相关分类