Многопоточность с TPL - доступ к внутренним свойствам класса - PullRequest
0 голосов
/ 15 января 2020

Я использую библиотеку TPL для распараллеливания операции 2D-сетки. Я извлек простой пример из моего реального кода, чтобы проиллюстрировать, что я делаю. Я получаю желаемые результаты, которые мне нужны, и время вычислений увеличивается в зависимости от количества процессоров на моем ноутбуке (12).

Я бы хотел получить несколько советов или мнений о моем коде, чтобы узнать, как мои свойства объявлены. Опять же, это работает, как ожидалось, но интересно, может ли дизайн быть лучше. Заранее спасибо.

Мой упрощенный код:

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

namespace Gridding
{


    public abstract class Base
    {
        /// <summary>
        /// Values representing the mesh values where each node in the gridis assigned som value. 
        /// </summary>
        public float[,] Values { get; set; }
        public abstract void Compute();
    }


    public class Derived : Base
    {

        /// <summary>
        /// Make the mesh readonly.  Is this necessary?
        /// </summary>
        readonly Mesh MyMesh;

        Derived(Mesh mesh)
        {
            MyMesh = mesh;
        }


        public override void Compute()
        {
            Values = new float[MyMesh.NX, MyMesh.NY];

            double[] xn = MyMesh.GetXNodes();
            double[] yn = MyMesh.GetYNodes();

            /// Paralellize the threads along the columns of the grid using the Task Paralllel Library (TPL).
            Parallel.For(0, MyMesh.NX, i =>
            {
                Run(i, xn, yn);
            });
        }


        private void Run(int i, double[] xn, double[] yn)
        {
            /// Some long operation that parallelizes along the columns of a mesh/grid
            double x = xn[i];
            for (int j = 0; j < MyMesh.NY; j++)
            {

                /// Again, longer operation here
                double y = yn[j];

                double someValue = Math.Sqrt(x * y); 
                Values[i, j] = (float)someValue;
            }
        }


        static void Main(string[] args)
        {
            int nx = 100;
            int ny = 120;
            double x0 = 0.0;
            double y0 = 0.0;
            double width = 100;
            double height = 120;

            Mesh mesh = new Mesh(nx, ny, x0, y0, width, height);

            Base tplTest = new Derived(mesh);
            tplTest.Compute();

            float[,] values = tplTest.Values;

            Console.Read();


        }

        /// <summary>
        /// A simple North-South oriented grid.
        /// </summary>
        class Mesh
        {
            public int NX { get; } = 100;
            public int NY { get; set; } = 150;
            public double XOrigin { get; set; } = 0.0;
            public double YOrigin { get; set; } = 0.0;
            public double Width { get; set; } = 100.0;
            public double Height { get; set; } = 150.0;
            public double DX { get; }
            public double DY { get; }

            public Mesh(int nx, int ny, double xOrigin, double yOrigin, double width, double height)
            {
                NX = nx;
                NY = ny;
                XOrigin = xOrigin;
                YOrigin = yOrigin;
                Width = width;
                Height = height;
                DX = Width / (NX - 1);
                DY = Height / (NY - 1);
            }

            public double[] GetYNodes()
            {
                double[] yNodeLocs = new double[NY];
                for (int i = 0; i < NY; i++)
                {
                    yNodeLocs[i] = YOrigin + i * DY;
                }
                return yNodeLocs;
            }

            public double[] GetXNodes()
            {
                double[] xNodeLocs = new double[NX];
                for (int i = 0; i < NX; i++)
                {
                    xNodeLocs[i] = XOrigin + i * DX;
                }
                return xNodeLocs;
            }
        }
    }
}

1 Ответ

0 голосов
/ 15 января 2020

При наличии только от 100 до 150 элементов массива накладные расходы на параллелизм компенсируют усиление. Вы можете кэшировать результат GetXNodes() и GetYNodes() и аннулировать кэшированные значения при изменении XOrigin, NX, YOrigin или NY.

...