我理解gcc的--ffast-math标志可以大大提高浮动操作的速度,并超出IEEE标准,但我似乎无法找到有关它正在发生的事情的信息.任何人都可以解释一些细节,并可能给出一个明确的例子,说明如果标志开启或关闭会有什么变化?
我确实尝试过挖掘SO以寻找类似的问题,但却找不到任何解释ffast-math工作原理的东西.
我对使用Sandy-Bridge和Haswell可以完成每个核心每个循环的触发器感到困惑.据我所知,对于SSE,每个核心每个周期应该为4个触发器,对于AVX/AVX2,每个核心每个周期应该有8个触发器.
这似乎在这里得到验证, 如何实现每个周期4个FLOP的理论最大值? ,这里, Sandy-Bridge CPU规范.
然而,下面的链接似乎表明,Sandy-bridge每个核心每个周期可以执行16个触发器,每个核心每个循环使用Haswell 32个触发器 http://www.extremetech.com/computing/136219-intels-haswell-is-an-前所未有-threat-to-nvidia-amd.
谁可以给我解释一下这个?
编辑:我现在明白为什么我感到困惑.我认为术语FLOP仅指单浮点(SP).我现在看到如何在每个循环中实现理论最大值4 FLOP的测试?实际上是双浮点(DP),因此它们为SSE实现4个DP FLOP /周期,为AVX实现8个DP FLOP /周期.在SP上重做这些测试会很有趣.
我使用英特尔®架构代码分析器(IACA)发现了一些意想不到的东西(对我而言).
以下指令使用[base+index]寻址
addps xmm1, xmmword ptr [rsi+rax*1]
Run Code Online (Sandbox Code Playgroud)
根据IACA没有微熔丝.但是,如果我用[base+offset]这样的
addps xmm1, xmmword ptr [rsi]
Run Code Online (Sandbox Code Playgroud)
IACA报告它确实融合了.
英特尔优化参考手册的第2-11节给出了以下"可以由所有解码器处理的微融合微操作"的示例
FADD DOUBLE PTR [RDI + RSI*8]
Run Code Online (Sandbox Code Playgroud)
和Agner Fog的优化装配手册也给出了使用[base+index]寻址的微操作融合的例子.例如,请参见第12.2节"Core2上的相同示例".那么正确的答案是什么?
我是指令优化的新手.
我对一个简单的函数dotp进行了简单的分析,该函数用于获取两个浮点数组的点积.
C代码如下:
float dotp(
const float x[],
const float y[],
const short n
)
{
short i;
float suma;
suma = 0.0f;
for(i=0; i<n; i++)
{
suma += x[i] * y[i];
}
return suma;
}
Run Code Online (Sandbox Code Playgroud)
我用昂纳雾在网络上提供的测试框架testp.
在这种情况下使用的数组是对齐的:
int n = 2048;
float* z2 = (float*)_mm_malloc(sizeof(float)*n, 64);
char *mem = (char*)_mm_malloc(1<<18,4096);
char *a = mem;
char *b = a+n*sizeof(float);
char *c = b+n*sizeof(float);
float *x = (float*)a;
float *y = (float*)b;
float *z = (float*)c;
Run Code Online (Sandbox Code Playgroud)
然后我调用函数dotp,n = 2048,repeat …
如果我有一个受Intel jcc erratum约束的芯片,我如何在 gcc 中启用缓解(它调整分支位置以避免有问题的对齐),以及哪些 gcc 版本支持它?
我必须对相对较小的整数进行大量操作(加法),并且我开始考虑哪种数据类型在 64 位机器上能提供最佳性能。
\n我确信uint16将 4 加在一起所需的时间与 1 相同uint64,因为 ALU 可以uint16仅使用 1 个uint64加法器进行 4 次加法。(进位传播意味着这对于单个 64 位加法器来说并不容易,但这就是整数 SIMD 指令的工作原理。)
显然情况并非如此:
\nIn [3]: data = np.random.rand(10000)\n\nIn [4]: int16 = data.astype(np.uint16)\n\nIn [5]: int64 = data.astype(np.uint64)\n\nIn [6]: int32 = data.astype(np.uint32)\n\nIn [7]: float32 = data.astype(np.float32)\n\nIn [8]: float64 = data.astype(np.float64)\n\nIn [9]: %timeit int16.sum()\n13.4 \xc2\xb5s \xc2\xb1 43.3 ns per loop (mean \xc2\xb1 std. dev. of 7 runs, 100000 loops each)\n\nIn [10]: %timeit int32.sum()\n13.9 \xc2\xb5s \xc2\xb1 347 …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用simd内部函数在C中编程矩阵乘法。我非常确定自己的实现,但是执行时,我会从所得矩阵系数的第5位开始出现一些数字错误。
REAL_T只是具有typedef的浮点数
/* This is my matmul Version with simd, using floating simple precision*/
void matmul(int n, REAL_T *A, REAL_T *B, REAL_T *C){
int i,j,k;
__m256 vA, vB, vC, vRes;
for (i=0; i<n; i++){
for (j=0; j<n; j++){
for (k=0; k<n; k= k+8){
vA = _mm256_load_ps(&A[i*n+k]);
vB = _mm256_loadu_ps(&B[k*n+j]);
vC = _mm256_mul_ps(vA, vB);
vC = _mm256_hadd_ps(vC, vC);
vC = _mm256_hadd_ps(vC, vC);
/*To get the resulting coefficient, after doing 2 hadds,
I have to get the first and the last element …Run Code Online (Sandbox Code Playgroud) 我有一个循环,我正在尝试与 OpenMP 有效地并行化。它涉及累积矢量流的 L2 范数,并进行缩减。这是循环:
struct vec3
{
float data[3] = {};
};
float accumulate_eta_sq_t_mass(const vec3* etas, const float* masses, const std::size_t& n)
{
auto a = 0.0;
#pragma omp parallel for simd safelen(16) reduction(+:a)
for (auto ii = std::size_t{}; ii < n; ++ii)
{
const auto& eta = etas[ii];
const auto x = static_cast<double>(eta.data[0]);
const auto y = static_cast<double>(eta.data[1]);
const auto z = static_cast<double>(eta.data[2]);
const auto m = static_cast<double>(masses[ii]);
a += (x * x + y * y + …Run Code Online (Sandbox Code Playgroud) c++ benchmarking openmp performance-testing parallelism-amdahl