0

私は数値集中型のアプリケーションを使用しており、インターネットで GFLOPS を探した後、独自の小さなベンチマークを実行することにしました。約 1 秒の実行を得るために、シングル スレッドの行列乗算を何千回も実行しました。これは内側の loop.full です。

for (int i = 0; i < SIZEA; i++)
    for (int j = 0; j < SIZEB; j++)
        vector_out[i] = vector_out[i] + vector[j] * matrix[i, j];

FLOPS を扱ってから何年も経っているので、FLOP ごとに約 3 ~ 6 サイクルになると予想していました。しかし、私は 30 (100 MFLOPS) を取得しています。これを並列化すると、さらに多くの値が得られますが、それは期待していませんでした。これは dot NET の問題でしょうか。それともこれは本当にCPUのパフォーマンスですか?

これは、完全なベンチマーク コードのフィドルです。

編集: Visual Studio はリリース モードでも実行に時間がかかります。実行可能ファイル自体は、FLOP あたり 12 サイクル (250 MFLOPS) で実行されます。それでも VM への影響はありますか?

4

1 に答える 1

2

Your bench mark doesn't really measure FLOPS, it does some floating point operations and looping in C#.

However, if you can isolate your code to a repetition of just floating point operations you still have some problems.

Your code should include some "pre-cycles" to allow the "jitter to warm-up", so you are not measuring compile time.

Then, even if you do that,

You need to compile in release mode with optimizations on and execute your test from the commmand-line on a known consistent platform.


Fiddle here

Here is my alternative benchmark,

using System;
using System.Linq;
using System.Diagnostics;

class Program
{
    static void Main()
    {
        const int Flops = 10000000;
        var random = new Random();
        var output = Enumerable.Range(0, Flops)
                         .Select(i => random.NextDouble())
                         .ToArray();
        var left = Enumerable.Range(0, Flops)
                         .Select(i => random.NextDouble())
                         .ToArray();
        var right = Enumerable.Range(0, Flops)
                         .Select(i => random.NextDouble())
                         .ToArray();

        var timer = Stopwatch.StartNew();
        for (var i = 0; i < Flops - 1; i++)
        {
            unchecked
            {
                output[i] += left[i] * right[i];
            }
        }

        timer.Stop();
        for (var i = 0; i < Flops - 1; i++)
        {
            output[i] = random.NextDouble();
        }

        timer = Stopwatch.StartNew();
        for (var i = 0; i < Flops - 1; i++)
        {
            unchecked
            {
                output[i] += left[i] * right[i];
            }
        }

        timer.Stop();

        Console.WriteLine("ms: {0}", timer.ElapsedMilliseconds);
        Console.WriteLine(
            "MFLOPS: {0}",
            (double)Flops / timer.ElapsedMilliseconds / 1000.0);
    }
}

On my VM I get results like

ms: 73
MFLOPS: 136.986301...

Note, I had to increase the number of operations significantly to get over 1 millisecond.

于 2015-03-20T16:03:08.640 に答える