1

を表すギザギザの配列がありGrid、配列の各項目はCellです。Grid2600 行と 2600 列があります。それぞれの座標を計算し、オブジェクトCellのインスタンスを作成Cellして配列に追加する必要があります。現在、私が使用しているコードは3200-3800 ms私のコンピューター上で実行されます。速くする方法はありますか?

public GridCell[][] Cells;
private void CreateCells(int cellWidth, int cellHeight, int startX, int startY)
    {          
        Cells = new GridCell[RowsCount][];
        for (int i = 0; i < RowsCount; i++)
        {
            Cells[i] = new GridCell[ColumnsCount];
            for (int j = 0; j < ColumnsCount; j++)
            {
                Point coordinate = new Point(startX + cellWidth * j, startY + cellHeight * i);
                Cells[i][j] = new GridCell(cellWidth, cellHeight, coordinate);
            }
        }
    }
4

3 に答える 3

3

6760000 個のオブジェクトを操作していることを考えると、優れたパフォーマンスが得られます。そして、主な時間はおそらくヒープ上に新しいオブジェクトを構築するために費やされます。あなたが観察したように、クラスの代わりに構造を使用すると、ブーストが得られます。

CPU キャッシュが大きい場合は、次のような単一の配列を使用することもできます。

public GridCell[] Cells = new GridCell[RowsCount * ColumnsCount];

次のようなアドレス指定を使用します。

Cells[i * ColumnsCount + j] = x;
于 2013-07-23T03:58:56.173 に答える
2

Parallel.For の使用を検討してください - このようなものはマルチスレッドにとって簡単です。

示されているように、機能を変更する意思がある場合 (この場合は構造体を使用しますが、単一の配列を割り当てることにも利点がある場合があります) であれば、他の場所でより大きな初期ゲインを見つけることができますが、パフォーマンスを向上させるためにスレッドを使用することもできます。

いくつかの簡単なテスト:

//Single Threaded          : 1701, 1825, 1495, 1606
//Multi Threaded           : 1516, 1446, 1581, 1401
//Struct Single Threaded   :  154,  157,  153,  151
//Struct MultiThreaded     :  104,  107,  106,  103

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

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                Benchmark("Single Threaded", () => CreateCells(1, 1, 0, 0));
                Benchmark("Multi Threaded", () => CreateCellsThreaded(1, 1, 0, 0));
                Benchmark("Struct Single Threaded", () => CreateStructCells(1, 1, 0, 0));
                Benchmark("Struct MultiThreaded", () => CreateStructCellsThreaded(1, 1, 0, 0));
            }
        }

        static void Benchmark(string Name, Action test)
        {
            var sw = Stopwatch.StartNew();
            test();
            UpdateResults(Name, sw.ElapsedMilliseconds.ToString());
            GC.Collect();
        }

        static Dictionary<string, string> results = new Dictionary<string, string>();
        static void UpdateResults(string key, string value)
        {
            value = value.PadLeft(4);
            if (results.ContainsKey(key))
                results[key] += ", " + value;
            else
                results[key] = value;

            Console.Clear();
            foreach (var kvp in results) Console.WriteLine(kvp.Key.PadRight(25) + ": " + kvp.Value);
        }

        const int RowsCount = 2600;
        const int ColumnsCount = 2600;

        public class Point
        {
            public int x;
            public int y;
            public Point(int x, int y)
            {
                this.x = x;
                this.y = y;
            }
        }

        public class GridCell
        {
            public int width;
            public int height;
            public Point point;
            public GridCell(int width, int height, Point point)
            {
                this.width = width;
                this.height = height;
                this.point = point;
            }
        }

        public struct StructPoint
        {
            public int x;
            public int y;
            public StructPoint(int x, int y)
            {
                this.x = x;
                this.y = y;
            }
        }


        public struct StructGridCell
        {
            public int width;
            public int height;
            public StructPoint point;
            public StructGridCell(int width, int height, StructPoint point)
            {
                this.width = width;
                this.height = height;
                this.point = point;
            }
        }

        private static void CreateCells(int cellWidth, int cellHeight, int startX, int startY)
        {
            var Cells = new GridCell[RowsCount][];
            for (int i = 0; i < RowsCount; i++)
            {
                Cells[i] = new GridCell[ColumnsCount];
                for (int j = 0; j < ColumnsCount; j++)
                {
                    Point coordinate = new Point(startX + cellWidth * j, startY + cellHeight * i);
                    Cells[i][j] = new GridCell(cellWidth, cellHeight, coordinate);
                }
            }
        }
        private static void CreateCellsThreaded(int cellWidth, int cellHeight, int startX, int startY)
        {
            var Cells = new GridCell[RowsCount][];
            Parallel.For(0, RowsCount, new ParallelOptions { MaxDegreeOfParallelism = 4 }, i =>
            {
                Cells[i] = new GridCell[ColumnsCount];
                for (int j = 0; j < ColumnsCount; j++)
                {
                    Point coordinate = new Point(startX + cellWidth * j, startY + cellHeight * i);
                    Cells[i][j] = new GridCell(cellWidth, cellHeight, coordinate);
                }
            });
        }

        private static void CreateStructCells(int cellWidth, int cellHeight, int startX, int startY)
        {
            var Cells = new StructGridCell[RowsCount][];
            for (int i = 0; i < RowsCount; i++)
            {
                Cells[i] = new StructGridCell[ColumnsCount];
                for (int j = 0; j < ColumnsCount; j++)
                {
                    var coordinate = new StructPoint(startX + cellWidth * j, startY + cellHeight * i);
                    Cells[i][j] = new StructGridCell(cellWidth, cellHeight, coordinate);
                }
            }
        }
        private static void CreateStructCellsThreaded(int cellWidth, int cellHeight, int startX, int startY)
        {
            var Cells = new StructGridCell[RowsCount][];
            Parallel.For(0, RowsCount, i =>
            {
                Cells[i] = new StructGridCell[ColumnsCount];
                for (int j = 0; j < ColumnsCount; j++)
                {
                    var coordinate = new StructPoint(startX + cellWidth * j, startY + cellHeight * i);
                    Cells[i][j] = new StructGridCell(cellWidth, cellHeight, coordinate);
                }
            });
        }
    }
}
于 2013-07-23T03:58:23.563 に答える
1

コメントで、GridCellとの両方Pointがクラスであると述べました。クラスは、作成する最も一般的なものですが、さまざまなセマンティクスに問題がなく、ほとんどの場合、機能ではなくデータを保持する場合は、クラスを構造体に変換できます。

構造体はほとんどクラスに似ていますが、参照型ではなく値型です。これは、次のようなコードを意味します。

Point a = new Point(0, 0);
Point b = a;
b.X = 5;
Console.WriteLine(a);

0それが構造体であり5、クラスである場合は出力されます。

これらのセマンティクスにより、構造体を他のものに埋め込むことができ、ヒープ上に独自のスペースを持つ必要がなくなります。ヒープからの割り当てはコストがかかる可能性があるため、たとえば構造体の配列を割り当てることができる場合は、多数ではなく 1 つの割り当てだけで済みます。

于 2013-07-23T03:54:14.763 に答える