我发现C anc C#中类似代码之间存在巨大的性能差异.
C代码是:
#include <stdio.h>
#include <time.h>
#include <math.h>
main()
{
int i;
double root;
clock_t start = clock();
for (i = 0 ; i <= 100000000; i++){
root = sqrt(i);
}
printf("Time elapsed: %f\n", ((double)clock() - start) / CLOCKS_PER_SEC);
}
Run Code Online (Sandbox Code Playgroud)
而C#(控制台应用程序)是:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
DateTime startTime = DateTime.Now;
double root;
for (int i = 0; i <= 100000000; i++)
{
root = Math.Sqrt(i);
} …Run Code Online (Sandbox Code Playgroud) 有谁知道为什么GCC/Clang不会在下面的代码示例中优化函数test1,只是在使用fast-math选项时只使用RCPPS指令?是否有另一个编译器标志会生成此代码?
typedef float float4 __attribute__((vector_size(16)));
float4 test1(float4 v)
{
return 1.0f / v;
}
Run Code Online (Sandbox Code Playgroud)
您可以在此处查看已编译的输出:https://goo.gl/jXsqat
假设有必要计算打包浮点数据的倒数或倒数平方根.两者都可以轻松完成:
__m128 recip_float4_ieee(__m128 x) { return _mm_div_ps(_mm_set1_ps(1.0f), x); }
__m128 rsqrt_float4_ieee(__m128 x) { return _mm_div_ps(_mm_set1_ps(1.0f), _mm_sqrt_ps(x)); }
Run Code Online (Sandbox Code Playgroud)
这种方法效果很好但很慢:根据指南,它们在Sandy Bridge上进行了14次和28次循环(吞吐量).对应的AVX版本在Haswell上几乎占用相同的时间.
另一方面,可以使用以下版本:
__m128 recip_float4_half(__m128 x) { return _mm_rcp_ps(x); }
__m128 rsqrt_float4_half(__m128 x) { return _mm_rsqrt_ps(x); }
Run Code Online (Sandbox Code Playgroud)
它们只需要一到两个时间周期(吞吐量),从而大大提升了性能.但是,它们非常接近:它们产生的结果相对误差小于1.5*2 ^ -12.鉴于单精度浮点数的机器epsilon是2 ^?24,我们可以说这种近似具有大约一半的精度.
似乎可以添加Newton-Raphson迭代以产生具有单精度的结果(可能不像IEEE标准所要求的那样精确),参见GCC,ICC,LLVM上的讨论.理论上,相同的方法可用于双精度值,产生半精度或单精度或双精度.
我有兴趣为float和double数据类型以及所有(half,single,double)精度实现此方法的实现.处理特殊情况(除以零,sqrt(-1),inf/nan等)不是必需的.此外,我不清楚这些例程中的哪一个比普通的IEEE编译解决方案更快,哪个更慢.
以下是对答案的一些小限制,请:
欢迎任何性能评估,测量和讨论.
以下是具有一次NR迭代的单精度浮点数的版本:
__m128 recip_float4_single(__m128 x) {
__m128 res = _mm_rcp_ps(x);
__m128 muls …Run Code Online (Sandbox Code Playgroud) 在我正在分析的应用程序中,我发现在某些情况下,此功能可以占用总执行时间的10%.
正在使用MSVC++ 2008编译器,以供参考......我不记得modf是否映射到单个指令,或者是否有可能使其更快.
另见这里关于sqrt函数的类似问题
与sqrt不同,我真的不知道modf是如何工作的.有装配操作吗?例如,您可以这样做:
modf(float input,int &intPart, float &floatPart)
{
intPart= (int)input;
floatPart= input - intPart;
}
Run Code Online (Sandbox Code Playgroud)
但我认为这会导致施法/转换等处罚,快速实施如何运作?