C#多线程-系统的性能和体系结构

C#多线程-系统的性能和体系结构,c#,multithreading,performance,C#,Multithreading,Performance,因此,我正在开发一个C#应用程序,它相当占用CPU 目前我正在使用ThreadPool异步处理任务,但事实证明这并不像我预期的那样有效 以这个类为例,我使用它检索一个构建器类来生成一个块 public class ChunkBuilderProvider { private readonly BlockingCollection<ChunkBuilder> Builders; public ChunkBuilderProvider() { B

因此,我正在开发一个C#应用程序,它相当占用CPU

目前我正在使用ThreadPool异步处理任务,但事实证明这并不像我预期的那样有效

以这个类为例,我使用它检索一个构建器类来生成一个块

public class ChunkBuilderProvider
{
    private readonly BlockingCollection<ChunkBuilder> Builders;

    public ChunkBuilderProvider()
    {
        Builders = new BlockingCollection<ChunkBuilder>();
        for (int i = 0; i < Configs.BuilderMaxInstance; i++)
            Builders.Add(new ChunkBuilder());
    }

    public ChunkBuilder GetBuilder()
    {
        ChunkBuilder c;
        return Builders.TryTake(out c, -1) ? c : null;
    }

    public void ReplaceBuilder(ChunkBuilder c)
    {
        Builders.Add(c);
    }

    public int IdleBuilders()
    {
        return Builders.Count;
    }

    internal bool Build(Chunk c)
    {
        if (c.State == Chunk.ChunkState.Generating)
            return false;
        var b = GetBuilder();
        if (b == null)
            return false;
        ThreadPool.QueueUserWorkItem(a =>
        {
            b.Generate(c);
            ReplaceBuilder(b);
        });
        return true;
    }
}
公共类ChunkBuilderProvider
{
私有只读阻止集合生成器;
公共ChunkBuilderProvider()
{
Builders=newblockingcollection();
对于(int i=0;i
{
b、 生成(c);
建筑商(b);
});
返回true;
}
}
生成任务是非常CPU密集型的,使用5个构建器运行它,使我的CPU使用率达到100%

蚂蚁告诉我:

[好像我不能在这里发布图片]

编辑:CPU密集型代码如下:

    using System;
using System.Collections.Generic;
using HyroVoxelEngine.Graphics.Primitives;
using HyroVoxelEngine.Voxels.Blocks;
using HyroVoxelEngine.Voxels.Chunks;
using SharpDX;


namespace HyroVoxelEngine.Voxels.Meshing
{
    public class GreedyMeshing
    {
        private static readonly int[][][] VerticesOffset = new int[6][][]
        {
//TOP
            new int[9][]
            {
                new int[3] {-1, 1, 1}, new int[3] {0, 1, 1}, new int[3] {1, 1, 1}, new int[3] {-1, 1, 0}, new int[3] {0, 1, 0}, new int[3] {1, 1, 0}, new int[3] {-1, 1, -1},
                new int[3] {0, 1, -1}, new int[3] {1, 1, -1}
            },
//North
            new int[9][]
            {
                new int[3] {-1, -1, 1}, new int[3] {0, -1, 1}, new int[3] {1, -1, 1}, new int[3] {-1, 0, 1}, new int[3] {0, 0, 1}, new int[3] {1, 0, 1}, new int[3] {-1, 1, 1},
                new int[3] {0, 1, 1}, new int[3] {1, 1, 1}
            },
//Bottom
            new int[9][]
            {
                new int[3] {-1, -1, -1}, new int[3] {0, -1, -1}, new int[3] {1, -1, -1}, new int[3] {-1, -1, 0}, new int[3] {0, -1, 0}, new int[3] {1, -1, 0}, new int[3] {-1, -1, 1},
                new int[3] {0, -1, 1}, new int[3] {1, -1, 1}
            },
//SOUTH
            new int[9][]
            {
                new int[3] {-1, 1, -1}, new int[3] {0, 1, -1}, new int[3] {1, 1, -1}, new int[3] {-1, 0, -1}, new int[3] {0, 0, -1}, new int[3] {1, 0, -1}, new int[3] {-1, -1, -1},
                new int[3] {0, -1, -1}, new int[3] {1, -1, -1}
            },
//West
            new int[9][]
            {
                new int[3] {1, 1, 1}, new int[3] {1, 0, 1}, new int[3] {1, -1, 1}, new int[3] {1, 1, 0}, new int[3] {1, 0, 0}, new int[3] {1, -1, 0}, new int[3] {1, 1, -1},
                new int[3] {1, 0, -1}, new int[3] {1, -1, -1}
            },
//East
            new int[9][]
            {
                new int[3] {-1, -1, 1}, new int[3] {-1, 0, 1}, new int[3] {-1, 1, 1}, new int[3] {-1, -1, 0}, new int[3] {-1, 0, 0}, new int[3] {-1, 1, 0}, new int[3] {-1, -1, -1},
                new int[3] {-1, 0, -1}, new int[3] {-1, 1, -1}
            }
        };

        private Block[][][] Blocks;
        private List<int> Index;
        private int VOXEL_SIZE = 1;
        private Chunk chunk;
        private List<VoxelVertex> vertices;
        public void SetChunk(Chunk c)
        {
            chunk = c;
            Blocks = c.Blocks;
        }
        public ChunkPrimitive Greedy()
        {
            Index = new List<int>(10000);
            vertices = new List<VoxelVertex>(8000);
            /*
         * These are just working variables for the algorithm - almost all taken 
         * directly from Mikola Lysenko's javascript implementation.
         */
            int i, j, k, l, w, h, u, v, n;
            var side = VoxelFace.Direction.None;
            int[] x = {0, 0, 0};
            int[] q = {0, 0, 0};
            int[] du = {0, 0, 0};
            int[] dv = {0, 0, 0};
            /*
         * We create a mask - this will contain the groups of matching voxel faces 
         * as we proceed through the chunk in 6 directions - once for each face.
         */
            VoxelFace voxelFace, voxelFace1;
            int[] Dimensions = {Chunk.SizeX, Chunk.SizeY, Chunk.SizeZ};
            VoxelFace[] mask;
            /**
         * We start with the lesser-spotted boolean for-loop (also known as the old flippy floppy). 
         * 
         * The variable backFace will be TRUE on the first iteration and FALSE on the second - this allows 
         * us to track which direction the indices should run during creation of the quad.
         * 
         * This loop runs twice, and the inner loop 3 times - totally 6 iterations - one for each 
         * voxel face.
         */
            for (bool backFace = true, b = false; b != backFace; backFace = backFace && b, b = !b)
            {
                /*
             * We sweep over the 3 dimensions - most of what follows is well described by Mikola Lysenko 
             * in his post - and is ported from his Javascript implementation.  Where this implementation 
             * diverges, I've added commentary.
             */
                for (int d = 0; d < 3; d++)
                {
                    /*
                 * These are just working variables to hold two faces during comparison.
                 */
                    u = (d + 1)%3;
                    v = (d + 2)%3;
                    x[0] = 0;
                    x[1] = 0;
                    x[2] = 0;
                    q[0] = 0;
                    q[1] = 0;
                    q[2] = 0;
                    q[d] = 1;
                    mask = new VoxelFace[Dimensions[u]*Dimensions[v]];
                    /*
                 * Here we're keeping track of the side that we're meshing.
                 */
                    if (d == 0)
                        side = backFace ? VoxelFace.Direction.West : VoxelFace.Direction.East;
                    else if (d == 1)
                        side = backFace ? VoxelFace.Direction.Bottom : VoxelFace.Direction.Top;
                    else if (d == 2)
                        side = backFace ? VoxelFace.Direction.South : VoxelFace.Direction.North;
                    /*
                 * We move through the dimension from front to back
                 */
                    for (x[d] = -1; x[d] < Dimensions[d];)
                    {
                        n = 0;
                        for (x[v] = 0; x[v] < Dimensions[v]; x[v]++)
                        {
                            for (x[u] = 0; x[u] < Dimensions[u]; x[u]++)
                            {
                                /*
                             * Here we retrieve two voxel faces for comparison.
                             */
                                voxelFace = (x[d] >= 0) ? getVoxelFace(x[0], x[1], x[2], side) : null;
                                voxelFace1 = (x[d] < Dimensions[d] - 1) ? getVoxelFace(x[0] + q[0], x[1] + q[1], x[2] + q[2], side) : null;
                                mask[n++] = ((voxelFace != null && voxelFace1 != null && voxelFace.Equals(voxelFace1))) ? null : backFace ? voxelFace1 : voxelFace;
                            }
                        }
                        x[d]++;
                        /*
                     * Now we generate the mesh for the mask
                     */
                        n = 0;
                        for (j = 0; j < Dimensions[v]; j++)
                        {
                            for (i = 0; i < Dimensions[u];)
                            {
                                if (mask[n] != null)
                                {
                                    /*
                                 * We compute the width
                                 */
                                    for (w = 1; i + w < Dimensions[u] && mask[n + w] != null && mask[n + w].Equals(mask[n]); w++) {}
                                    /*
                                 * Then we compute height
                                 */
                                    bool done = false;
                                    for (h = 1; j + h < Dimensions[v]; h++)
                                    {
                                        for (k = 0; k < w; k++)
                                        {
                                            if (mask[n + k + h*Dimensions[u]] == null || !mask[n + k + h*Dimensions[u]].Equals(mask[n]))
                                            {
                                                done = true;
                                                break;
                                            }
                                        }
                                        if (done)
                                            break;
                                    }
                                    /*
                                 * Here we check the "transparent" attribute in the VoxelFace class to ensure that we don't mesh 
                                 * any culled faces.
                                 */
                                    if (!mask[n].Transparent)
                                    {
                                        /*
                                     * Add quad
                                     */
                                        x[u] = i;
                                        x[v] = j;
                                        du[0] = 0;
                                        du[1] = 0;
                                        du[2] = 0;
                                        du[u] = w;
                                        dv[0] = 0;
                                        dv[1] = 0;
                                        dv[2] = 0;
                                        dv[v] = h;
                                        /*
                                     * And here we call the quad function in order to render a merged quad in the scene.
                                     * 
                                     * We pass mask[n] to the function, which is an instance of the VoxelFace class containing 
                                     * all the attributes of the face - which allows for variables to be passed to shaders - for 
                                     * example lighting values used to create ambient occlusion.
                                     */
                                        Quad(new Vector3(x[0], x[1], x[2]), new Vector3(x[0] + du[0], x[1] + du[1], x[2] + du[2]),
                                            new Vector3(x[0] + du[0] + dv[0], x[1] + du[1] + dv[1], x[2] + du[2] + dv[2]), new Vector3(x[0] + dv[0], x[1] + dv[1], x[2] + dv[2]), w, h,
                                            mask[n], backFace);
                                    }
                                    /*
                                 * We zero out the mask
                                 */
                                    for (l = 0; l < h; ++l)
                                    {
                                        for (k = 0; k < w; ++k)
                                            mask[n + k + l*Dimensions[u]] = null;
                                    }
                                    /*
                                 * And then finally increment the counters and continue
                                 */
                                    i += w;
                                    n += w;
                                }
                                else
                                {
                                    i++;
                                    n++;
                                }
                            }
                        }
                    }
                }
            }
            if (vertices.Count == 0 || Index.Count == 0)
                return null;
            return new ChunkPrimitive(vertices.ToArray(), Index.ToArray());
        }
        private VoxelFace getVoxelFace(int x, int y, int z, VoxelFace.Direction side)
        {
            VoxelFace voxelFace = new VoxelFace(side);
            voxelFace.Type = Blocks[x][y][z].Type;
            voxelFace.Light = chunk.LightValue[x][y][z];
            voxelFace.Side = side;
            voxelFace.LightSettings = CountSolidCorner(voxelFace, x, y, z);
            return voxelFace;
        }

        private int[] CountSolidCorner(VoxelFace voxelFace, int x, int y, int z)
        {
            var side = voxelFace.Side;
            int bottomLeft = 0;
            int bottomRight = 0;
            int TopLeft = 0;
            int TopRight = 0;
            var pos = new Vector3(x, y, z);

            #region TOP BOTOM

            //SOUTH = -z
            //NORTH = +z
            //West = -X
            //est = X;
            int[][] vertOff = VerticesOffset[(int) side];
            if (GetBlockSolid(vertOff[6], x, y, z))
                bottomLeft++;
            if (GetBlockSolid(vertOff[8], x, y, z))
                bottomRight++;
            if (GetBlockSolid(vertOff[2], x, y, z))
                TopRight++;
            if (GetBlockSolid(vertOff[0], x, y, z))
                TopLeft++;
            if (GetBlockSolid(vertOff[1], x, y, z))
            {
                TopLeft++;
                TopRight++;
            }
            if (GetBlockSolid(vertOff[7], x, y, z))
            {
                bottomLeft++;
                bottomRight++;
            }
            if (GetBlockSolid(vertOff[3], x, y, z))
            {
                TopLeft++;
                bottomLeft++;
            }
            if (GetBlockSolid(vertOff[5], x, y, z))
            {
                TopRight++;
                bottomRight++;
            }

            if (side == VoxelFace.Direction.Bottom)
                return new[] {TopLeft, TopRight, bottomLeft, bottomRight};
            if (side == VoxelFace.Direction.Top)
                return new[] {bottomLeft, bottomRight, TopLeft, TopRight};
            if (side == VoxelFace.Direction.West)
                return new[] {bottomLeft, TopLeft, bottomRight, TopRight};
            if (side == VoxelFace.Direction.East)
                return new[] {bottomRight, TopRight, bottomLeft, TopLeft};
            if (side == VoxelFace.Direction.North)
                return new[] {TopLeft, bottomLeft, TopRight, bottomRight};

            #endregion

            //COM x Positivo
            //TOP -  TR - BR - TL - BL
            return new[] {4, 4, 4, 4};
        }

        private bool GetBlockSolid(int[] offset, int x, int y, int z)
        {
            x = x + offset[0];
            y = y + offset[1];
            z = z + offset[2];
            if (x  < 0 | y  < 0 | z < 0)
                return true;
            if (x  >= Chunk.SizeX | y  >= Chunk.SizeY | z  >= Chunk.SizeZ)
                return true;
            return !Block.IsSolidBlock(Blocks[x][y ][z ].Type);
        }
        private void Quad(Vector3 bottomLeft, Vector3 topLeft, Vector3 topRight, Vector3 bottomRight, int width, int height, VoxelFace voxel, bool backFace)
        {
            BlockTexture texture = new BlockTexture();
            Vector2[] UVList = new Vector2[4];
            var vert = new VoxelVertex[4];
            Vector3 normal = voxel.Normal;
            if (voxel.Side == VoxelFace.Direction.Top) {}
            //switch (voxel.Side)
            //{
            //    case VoxelFace.Direction.Bottom:
            //        normal = - Vector3.UnitY;
            //        texture = TextureHelper.GetTexture(voxel.Type, BlockFaceDirection.YDecreasing);
            //        UVList = TextureHelper.GetUVMapping((int) texture, BlockFaceDirection.YDecreasing);
            //        break;
            //    case VoxelFace.Direction.Top:
            //        normal = Vector3.UnitY;
            //        texture = TextureHelper.GetTexture(voxel.Type, BlockFaceDirection.YIncreasing);
            //        UVList = TextureHelper.GetUVMapping((int) texture, BlockFaceDirection.YIncreasing);
            //        break;
            //    case VoxelFace.Direction.West:
            //        normal = Vector3.UnitX;
            //        texture = TextureHelper.GetTexture(voxel.Type, BlockFaceDirection.XIncreasing);
            //        UVList = TextureHelper.GetUVMapping((int) texture, BlockFaceDirection.XIncreasing);
            //        break;
            //    case VoxelFace.Direction.East:
            //        normal = -Vector3.UnitX;
            //        texture = TextureHelper.GetTexture(voxel.Type, BlockFaceDirection.XDecreasing);
            //        UVList = TextureHelper.GetUVMapping((int) texture, BlockFaceDirection.XDecreasing);
            //        break;
            //    case VoxelFace.Direction.North:
            //        normal = -Vector3.UnitZ;
            //        texture = TextureHelper.GetTexture(voxel.Type, BlockFaceDirection.ZDecreasing);
            //        UVList = TextureHelper.GetUVMapping((int) texture, BlockFaceDirection.ZDecreasing);
            //        break;
            //    case VoxelFace.Direction.South:
            //        normal = Vector3.UnitZ;
            //        texture = TextureHelper.GetTexture(voxel.Type, BlockFaceDirection.ZIncreasing);
            //        UVList = TextureHelper.GetUVMapping((int) texture, BlockFaceDirection.ZIncreasing);
            //        break;
            //}
            int ic = (Index.Count/6)*4;
            int[] indexes = !backFace ? new[] {2, 0, 1, 1, 3, 2} : new[] {2, 3, 1, 1, 0, 2};
            vert[0] = new VoxelVertex(bottomLeft*(VOXEL_SIZE), normal, UVList[0], new Vector3(voxel.Light, voxel.LightSettings[0], (int) (voxel.Side)));
            vert[1] = new VoxelVertex(bottomRight*(VOXEL_SIZE), normal, UVList[1], new Vector3(voxel.Light, voxel.LightSettings[1], (int) (voxel.Side)));
            vert[2] = new VoxelVertex(topLeft*(VOXEL_SIZE), normal, UVList[2], new Vector3(voxel.Light, voxel.LightSettings[2], (int) (voxel.Side)));
            vert[3] = new VoxelVertex(topRight*(VOXEL_SIZE), normal, UVList[3], new Vector3(voxel.Light, voxel.LightSettings[3], (int) (voxel.Side)));
            if (voxel.LightSettings[0] + voxel.LightSettings[3] > voxel.LightSettings[1] + voxel.LightSettings[2])
                indexes = !backFace ? new[] {0, 1, 3, 3, 2, 0} : new[] {0, 2, 3, 3, 1, 0};

            //int[] indexes = !backFace ? new[] { 0, 3, 2, 2, 1, 0 } : new[] { 0, 1, 2, 2, 0, 2 };
            Index.Add(indexes[0] + ic);
            Index.Add(indexes[1] + ic);
            Index.Add(indexes[2] + ic);
            Index.Add(indexes[3] + ic);
            Index.Add(indexes[4] + ic);
            Index.Add(indexes[5] + ic);
            vertices.Add(vert[0]);
            vertices.Add(vert[1]);
            vertices.Add(vert[2]);
            vertices.Add(vert[3]);
        }

        internal void Dispose()
        {
            throw new NotImplementedException();
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用hyrovoxelnengine.Graphics.Primitives;
使用HyroVoxelEngine.Voxels.Blocks;
使用hyrovoxelnengine.Voxels.Chunks;
使用SharpDX;
命名空间HyroVoxelEngine.Voxels.Meshing
{
公共类GreedyMeshing
{
私有静态只读int[][]VerticesOffset=new int[6][]
{
//顶
新整数[9][]
{
新int[3]{-1,1,1},新int[3]{0,1,1},新int[3]{1,1,1},新int[3]{-1,1,0},新int[3]{0,1,0},新int[3]{1,1,0},新int[3]{-1,1,1,1},
新int[3]{0,1,-1},新int[3]{1,1,-1}
},
//北
新整数[9][]
{
新int[3]{-1,-1,1},新int[3]{0,-1,1},新int[3]{1,-1,1},新int[3]{-1,0,1},新int[3]{0,0,1},新int[3]{1,0,1},新int[3]{-1,1,1},
新int[3]{0,1,1},新int[3]{1,1,1}
},
//底部
新整数[9][]
{
新整数[3]{-1,-1,-1},新整数[3]{0,-1,-1},新整数[3]{1,-1,-1},新整数[3]{-1,-1,0},新整数[3]{0,-1,0},新整数[3]{1,-1,0},新整数[3]{-1,-1,1},
新int[3]{0,-1,1},新int[3]{1,-1,1}
},
//南方
新整数[9][]
{
新int[3]{-1,1,-1},新int[3]{0,1,-1},新int[3]{1,1,-1},新int[3]{-1,0,-1},新int[3]{0,0,-1},新int[3]{1,0,-1},新int[3]{-1,-1},
新整数[3]{0,-1,-1},新整数[3]{1,-1}
},
//西部
新整数[9][]
{
新int[3]{1,1,1},新int[3]{1,0,1},新int[3]{1,-1,1},新int[3]{1,1,0},新int[3]{1,0,0},新int[3]{1,-1,0},新int[3]{1,1,-1},
新int[3]{1,0,-1},新int[3]{1,-1,-1}
},
//东边
新整数[9][]
{
新整数[3]{-1,-1,1},新整数[3]{-1,0,1},新整数[3]{-1,1,1},新整数[3]{-1,-1,0},新整数[3]{-1,0,0},新整数[3]{-1,1,0},新整数[3]{-1,1,1},
新整数[3]{-1,0,-1},新整数[3]{-1,1,-1}
}
};
专用块[][][]块;
私有列表索引;
私有int体素_SIZE=1;
私有块;
私有列表顶点;
公共void集块(块c)
{
chunk=c;
块=c.块;
}
公共组块()
{
索引=新列表(10000);
顶点=新列表(8000);
/*
*这些仅仅是算法的工作变量——几乎所有的变量都被采用了
*直接来自Mikola Lysenko的javascript实现。
*/
int i,j,k,l,w,h,u,v,n;
var side=体素面.Direction.None;
int[]x={0,0,0};
int[]q={0,0,0};
int[]du={0,0,0};
int[]dv={0,0,0};
/*
*我们创建一个遮罩-它将包含匹配体素面的组
*当我们从6个方向穿过区块时-每个面一次。
*/
体素面体素面,体素面1;
int[]维度={Chunk.SizeX,Chunk.SizeY,Chunk.SizeZ};
体素面[]掩模;
/**
*我们从较少斑点的布尔for循环(也称为旧的flippy软盘)开始。
* 
*变量backFace在第一次迭代时为TRUE,在第二次迭代时为FALSE-这允许
*我们需要跟踪在创建四边形期间索引应该运行的方向。
* 
*这个循环运行两次,内部循环运行3次-总共6次-每个循环一次
*体素脸。
*/
for(bool backFace=true,b=false;b!=backFace;backFace=backFace&&b,b=!b)
{
/*
*我们浏览了3个维度——米科拉·莱森科(Mikola Lysenko)很好地描述了以下大部分内容
*在他的博文中,从他的Javascript实现移植而来
*分歧,我添加了评论。
*/
对于(int d=0;d<3;d++)
{
/*
*这些只是在比较过程中保持两个面的工作变量。
*/
u=(d+1)%3;
v=(d+2)%3;
x[0]=0;
x[
using System.Threading.Tasks;

...

public IEnumerable<Chunk> GetChunks()
{
    // Here you can return the whole chunks collection or yield them one by one.
    yield return new Chunk();
}

public void DoIt()
{
    ChunkBuilder builder = new ChunkBuilder();
    ParallelOptions options = new ParallelOptions() {
        MaxDegreeOfParallelism = 4
    };
    Parallel.ForEach(this.GetChunks(), options, chunk => builder.Generate(chunk));
}
    Parallel.ForEach(this.GetChunks(), options, chunk => new ChunkBuilder().Generate(chunk));