为什么这个简单的F#代码比C#/ C ++版本慢36倍?

用户名

我编写了一个简单的测试,该测试创建一个变量,将其初始化为零,并递增100000000次。

C ++在0.36 s内完成了它。最初的C#版本仅需0.33s,而12秒内仅需0.8s F#。

我不使用任何功能,因此默认情况下通用没有问题

F#代码

open System
open System.Diagnostics
// Learn more about F# at http://fsharp.org
// See the 'F# Tutorial' project for more help.
[<EntryPoint>]
let main argv = 
    let N = 100000000
    let mutable x = 0
    let watch = new Stopwatch();
    watch.Start();
    for i in seq{1..N} do
        x <- (x+1)
    printfn "%A" x
    printfn "%A" watch.Elapsed
    Console.ReadLine()
        |> ignore
    0 // return an integer exit code

C ++代码

#include<stdio.h>
#include<string.h>
#include<vector>
#include<iostream>
#include<time.h>
using namespace std;
int main()
{
    const int N = 100000000;
    int x = 0;
    double start = clock();
    for(int i=0;i<N;++i)
    {
        x = x + 1;
    }
    printf("%d\n",x);
    printf("%.4lf\n",(clock() - start)/CLOCKS_PER_SEC);
    return 0;
}

C#代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

namespace SpeedTestCSharp
{
    class Program
    {
        static void Main(string[] args)
        {
            const int N = 100000000;
            int x = 0;
            Stopwatch watch = new Stopwatch();
            watch.Start();

            foreach(int i in Enumerable.Range(0,N))
            //Originally it was for(int i=0;i<N;++i)
            {
                x = x + 1;
            }
            Console.WriteLine(x);
            Console.WriteLine(watch.Elapsed);
            Console.ReadLine();
        }
    }
}

编辑

替换for (int i = 0; i < N; ++i)foreach(int i in Enumerable.Range(0,N))C#程序可以在0.8s左右的时间内运行,但仍比f#快得多

编辑

更换DateTimeStopWatch的为F#/ C#。结果是一样的

内在之光

这肯定是由于使用表达式而直接发生的:

for i in seq{1..N} do

在我的机器上,结果如下:

1亿

00:00:09.1500924

如果我将循环更改为:

for i in 1..N do

结果发生了巨大变化:

1亿

00:00:00.1001864

为什么?

这两种方法生成的IL完全不同。第二种情况,使用1..N语法的方式与C#for(int i=1; i<N+1; ++i)循环相同。

第一种情况非常不同,此版本产生完整序列,然后由foreach循环枚举。

所使用的C#和F#版本IEnumerables不同,因为它们使用不同的范围函数来生成它们。

C#版本用于System.Linq.Enumerable.RangeIterator生成值范围,而F#版本使用Microsoft.FSharp.Core.Operators.OperatorIntrinsics.RangeInt32我认为可以肯定地说,在这种特殊情况下,我们在C#和F#版本之间看到的性能差异是这两个函数的性能特征造成的。

svick在其注释中指出+操作符实际上是作为参数传递给integralRangeStep函数的,这是正确

对于非平凡的情况,n <> m这会导致使用ProperIntegralRangeEnumerator以下实现的F#编译器https : //github.com/Microsoft/visualfsharp/blob/master/src/fsharp/FSharp.Core/prim-types.fs #L6463

let inline integralRangeStepEnumerator (zero,add,n,step,m,f) : IEnumerator<_> =
    // Generates sequence z_i where z_i = f (n + i.step) while n + i.step is in region (n,m)
    if n = m then
        new SingletonEnumerator<_> (f n) |> enumerator 
    else
        let up = (n < m)
        let canStart = not (if up then step < zero else step > zero) // check for interval increasing, step decreasing 
        // generate proper increasing sequence
        { new ProperIntegralRangeEnumerator<_,_>(n,m) with 
                member x.CanStart = canStart
                member x.Before a b = if up then (a < b) else (a > b)
                member x.Equal a b = (a = b)
                member x.Step a = add a step
                member x.Result a = f a } |> enumerator

我们可以看到单步执行Enumerator会导致对提供的add函数的调用,而不是更直接直接的加法。

注意:所有计时都在“释放”模式下运行(尾部呼叫:打开,优化:打开)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么此F#代码比C#慢一些?

来自分类Dev

与C#相比,简单循环上的F#代码性能不佳-为什么?

来自分类Dev

C++,自使用 boost 和 std::chrono 以来的时间?为什么 Boost 版本慢 10 倍?

来自分类Dev

为什么我的C ++代码比LeetCode上的C代码慢三倍?

来自分类Dev

为什么这种简单的C ++添加比等效的Java慢6倍?

来自分类Dev

Swift比C和Python代码慢1000倍吗?

来自分类Dev

这个简单的C代码发生了什么?

来自分类Dev

即使生成的机器代码几乎相同,为什么C#的速度是C ++的两倍?

来自分类Dev

为什么在此图像处理测试中,Swift比C慢100倍?

来自分类Dev

为什么这个'C'代码的输出是这样的?

来自分类Dev

为什么这个简单的C ++代码无法与clang ++一起编译?

来自分类Dev

为什么这个简单的C ++代码无法与clang ++一起编译?

来自分类Dev

为什么此D代码比类似的C#实现慢?

来自分类Dev

为什么C#任务并行库代码比普通的for循环慢?

来自分类Dev

为什么我的C程序比同等的C#慢?

来自分类Dev

为什么我的C程序比同等的C#慢?

来自分类Dev

一个ffmpeg实例/内部版本比其他ffmpeg实例/内部版本慢3倍。为什么?

来自分类Dev

从C#执行F#源代码

来自分类Dev

使用Java基本数组的clojure代码比scala版本慢70倍

来自分类Dev

简单的C ++代码...为什么要编译?

来自分类Dev

为什么该程序的F#版本比Haskell的F#版本快6倍?

来自分类Dev

如何使这个简单的C#代码更高效/更优雅

来自分类Dev

这个简单的#define C代码有什么问题?

来自分类Dev

这个简单的代码(目标c)有什么问题?

来自分类Dev

为什么<会比<=慢?[C]

来自分类Dev

为什么这个 C# 代码乱序执行?不是 ASYNC(至少我认为不是)

来自分类Dev

什么是F#尾声?为什么与C#相比性能有所提高?

来自分类Dev

使用异步,相当于C#代码的F#是什么?

来自分类Dev

为什么在F#中不编译匹配的代码版本

Related 相关文章

  1. 1

    为什么此F#代码比C#慢一些?

  2. 2

    与C#相比,简单循环上的F#代码性能不佳-为什么?

  3. 3

    C++,自使用 boost 和 std::chrono 以来的时间?为什么 Boost 版本慢 10 倍?

  4. 4

    为什么我的C ++代码比LeetCode上的C代码慢三倍?

  5. 5

    为什么这种简单的C ++添加比等效的Java慢6倍?

  6. 6

    Swift比C和Python代码慢1000倍吗?

  7. 7

    这个简单的C代码发生了什么?

  8. 8

    即使生成的机器代码几乎相同,为什么C#的速度是C ++的两倍?

  9. 9

    为什么在此图像处理测试中,Swift比C慢100倍?

  10. 10

    为什么这个'C'代码的输出是这样的?

  11. 11

    为什么这个简单的C ++代码无法与clang ++一起编译?

  12. 12

    为什么这个简单的C ++代码无法与clang ++一起编译?

  13. 13

    为什么此D代码比类似的C#实现慢?

  14. 14

    为什么C#任务并行库代码比普通的for循环慢?

  15. 15

    为什么我的C程序比同等的C#慢?

  16. 16

    为什么我的C程序比同等的C#慢?

  17. 17

    一个ffmpeg实例/内部版本比其他ffmpeg实例/内部版本慢3倍。为什么?

  18. 18

    从C#执行F#源代码

  19. 19

    使用Java基本数组的clojure代码比scala版本慢70倍

  20. 20

    简单的C ++代码...为什么要编译?

  21. 21

    为什么该程序的F#版本比Haskell的F#版本快6倍?

  22. 22

    如何使这个简单的C#代码更高效/更优雅

  23. 23

    这个简单的#define C代码有什么问题?

  24. 24

    这个简单的代码(目标c)有什么问题?

  25. 25

    为什么<会比<=慢?[C]

  26. 26

    为什么这个 C# 代码乱序执行?不是 ASYNC(至少我认为不是)

  27. 27

    什么是F#尾声?为什么与C#相比性能有所提高?

  28. 28

    使用异步,相当于C#代码的F#是什么?

  29. 29

    为什么在F#中不编译匹配的代码版本

热门标签

归档