The Computer Language
Benchmarks Game

mandelbrot C# .NET Core #7 program

source code

/* The Computer Language Benchmarks Game
   http://benchmarksgame.alioth.debian.org/

   started with Java #2 program (Krause/Whipkey/Bennet/AhnTran/Enotus/Stalcup)
   adapted for C# by Jan de Vaan
   simplified and optimised to use TPL by Anthony Lloyd
   simplified to compute Cib alongside Crb by Tanner Gooding
   optimized to use Vector<double> by Tanner Gooding
*/

using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

public class MandelBrot
{
    // Vector<double>.Count is treated as a constant by the JIT, don't bother
    // storing it in a temporary variable anywhere below.

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static unsafe byte GetByte(double* pCrb, double Ciby, int x, int y)
    {
        var res = 0;

        for (var i = 0; i < 8; i += 2)
        {
            var Crbx = Unsafe.Read<Vector<double>>(pCrb + x + i);
            var Zr = Crbx;
            var vCiby = new Vector<double>(Ciby);
            var Zi = vCiby;

            var b = 0;
            var j = 49;

            do
            {
                var nZr = Zr * Zr - Zi * Zi + Crbx;
                Zi = Zr * Zi + Zr * Zi + vCiby;
                Zr = nZr;

                var t = Zr * Zr + Zi * Zi;

                if (t[0] > 4)
                {
                    b |= 2;

                    if (b == 3)
                    {
                        break;
                    }
                }

                if (t[1] > 4)
                {
                    b |= 1;

                    if (b == 3)
                    {
                        break;
                    }
                }

            } while (--j > 0);

            res = (res << 2) + b;
        }

        return (byte)(res ^ -1);
    }

    public static unsafe void Main(string[] args)
    {
        var size = (args.Length > 0) ? int.Parse(args[0]) : 200;

        var adjustedSize = size + (Vector<double>.Count * 8);
        adjustedSize &= ~(Vector<double>.Count * 8);

        var Crb = new double[adjustedSize];
        var Cib = new double[adjustedSize];

        fixed (double* pCrb = &Crb[0])
        fixed (double* pCib = &Cib[0])
        {
            var invN = new Vector<double>(2.0 / size);

            var onePtFive = new Vector<double>(1.5);
            var step = new Vector<double>(Vector<double>.Count);

            Vector<double> value;

            if (Vector<double>.Count == 2)
            {
                value = new Vector<double>(new double[] {
                    0, 1
                });
            }
            else if (Vector<double>.Count == 4)
            {
                value = new Vector<double>(new double[] {
                    0, 1, 2, 3
                });
            }
            else
            {
                value = new Vector<double>(new double[] {
                    0, 1, 2, 3, 4, 5, 6, 7
                });
            }

            for (var i = 0; i < size; i += Vector<double>.Count)
            {
                var t = value * invN;

                Unsafe.Write(pCrb + i, t - onePtFive);
                Unsafe.Write(pCib + i, t - Vector<double>.One);

                value += step;
            }
        }

        var lineLength = size >> 3;
        var data = new byte[adjustedSize * lineLength];

        fixed (double* pCrb = &Crb[0])
        {
            var _Crb = pCrb;

            Parallel.For(0, size, y => {
                var offset = y * lineLength;

                for (var x = 0; x < lineLength; x++)
                {
                    data[offset + x] = GetByte(_Crb, Cib[y], x * 8, y);
                }
            });
        }

        // generate the bitmap header
        Console.Out.Write("P4\n{0} {0}\n", size);
        Console.OpenStandardOutput().Write(data, 0, size * lineLength);
    }
}
    

notes, command-line, and program output

NOTES:
64-bit Ubuntu quad core
2.0.2 a04b4bf512
"System.GC.Server": true


Fri, 27 Oct 2017 00:38:20 GMT

MAKE:
cp mandelbrot.csharpcore-7.csharpcore Program.cs
cp Include/csharpcore/tmp.csproj .
cp Include/csharpcore/runtimeconfig.template.json .
mkdir obj
cp Include/csharpcore/tmp.csproj.nuget.g.props ./obj
cp Include/csharpcore/tmp.csproj.nuget.g.targets ./obj
/usr/bin/dotnet build -c Release
Microsoft (R) Build Engine version 15.4.8.50001 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  tmp -> /home/dunham/benchmarksgame_quadcore/mandelbrot/tmp/bin/Release/netcoreapp2.0/tmp.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:03.75

6.30s to complete and log all make actions

COMMAND LINE:
/usr/bin/dotnet ./bin/Release/netcoreapp2.0/tmp.dll 16000

(BINARY) PROGRAM OUTPUT NOT SHOWN