C# 如何对同一数组中的随机位置执行多线程操作?

C# 如何对同一数组中的随机位置执行多线程操作?,c#,arrays,multithreading,random,parallel-processing,C#,Arrays,Multithreading,Random,Parallel Processing,我有一个进程在Array中的随机位置上运行大量任务,并希望通过使用多线程来加速这一进程 它基本上是将“数组”中的一个位置随机化,检查其周围的值,如果满足一些特定条件,则更改随机位置值 有可能运行类似于 Parallel.For(0, n, s => { }); 循环而不是下面所示的while代码块来优化这个函数,那么一个代码块是什么样子的呢 我一直在考虑对所选元素使用一些“忙”属性,但这实际上使问题变得更加复杂 public void doStuffTothisArray(ref int

我有一个进程在
Array
中的随机位置上运行大量任务,并希望通过使用多线程来加速这一进程

它基本上是将“数组”中的一个位置随机化,检查其周围的值,如果满足一些特定条件,则更改随机位置值

有可能运行类似于

Parallel.For(0, n, s => { });
循环而不是下面所示的while代码块来优化这个函数,那么一个代码块是什么样子的呢

我一直在考虑对所选元素使用一些“忙”属性,但这实际上使问题变得更加复杂

public void doStuffTothisArray(ref int[,,] Array, ref IGenerator randomGenerator, int loops)
{
    int cc = 0;
    int sw = 0;
    do
    {
        if (doStuffOnRandomPositions(ref Array, ref randomGenerator))
            sw++; //if stuff was made counter

        if ((cc % (loops / 10)) == 0)
            Console.Write("{0} % \t", (cc / (loops / 10)) * 10); //some loading info

        cc++; //count iterations
    } while (cc < loops);
    Console.WriteLine("Stuff altered in {0} iterations: {1}", loops, sw);
}
public void dostuffttothisarray(ref int[,]数组,ref IGenerator randomGenerator,int循环)
{
int cc=0;
int-sw=0;
做
{
if(dostufforandompositions(参考数组,参考随机生成器))
sw++;//如果东西是用计数器制作的
如果((cc%(循环/10))==0)
Write(“{0}%\t”,(cc/(loops/10))*10);//一些加载信息
cc++;//计算迭代次数
}而(cc
后期编辑:

分割阵列并分配工作会破坏阵列的动态性,因为它需要是一个完整的系统

这是dostuff的原型…)

public static bool dostuffandompositions(参考晶格A,参考发电机rr)
{
position firstPos=新位置(rr.Next(0,A.n_大小)、rr.Next(0,A.n_大小)、rr.Next(0,A.n_大小));
位置secondPos=随机相邻位置(参考A、firstPos、参考rr);
//检查晶格中最近的3d邻居索引器
//Console.WriteLine(“第一:[{0},{1},{2}]\n第二:[{3},{4},{5}]\n”,第一位置x,第一位置y,第一位置z,第二位置x,第二位置y,第二位置z);
//获取坐标处的值
bool first=A.latticeArray[firstPos.x,firstPos.y,firstPos.z];
布尔秒=格子阵列[secondPos.x,secondPos.y,secondPos.z];
if(first==second)//如果它们是相等的状态,就不用麻烦了
返回false;
//检查周围环境的能量,以确定最终的自旋开关
int-surrBefore=surroundCheck(参考A,firstPos,first);//-surroundCheck(参考A,secondPos,second));
int-surrAfter=surroundCheck(参考A,firstPos,!first);//-surroundCheck(参考A,secondPos,!second));
if(surrAfter

在这种情况下,lattice类应该表示包含属性的“数组”。示例解决方案代码将非常感谢,因为我对c#方法有丰富的经验。

如果您的操作的范围是非相交的元素范围(如1-10、25-40、100-123),那么您可以在单独的范围内运行操作,而不是并行运行单个元素。如果在操作进行期间不重新分配阵列,则不需要任何其他同步


如果操作更改了随机元素,则必须进行适当的同步,并且可能无法从在多个线程上运行代码中获得任何好处。

鉴于您正在修改数组,这是共享状态,我看不出如何在不使用竞争条件的情况下对其进行优化。可能修改的索引是否基于RNG提供的选定索引确定?如果是这样,您可以构建同步,以防止在可能的修改可能重叠时出现并行性。只有当
dostufforrandompositions
足够复杂,足以保证额外的并行和同步开销时,这才有意义。为了避免竞争条件,您可以为每个项设置一个锁对象数组(或类似的同步)。这将取决于@Moho提到的对象的决定论,以及方法的复杂性。锁定这些多个对象也可能造成死锁。您必须设计锁定机制以避免这种情况。显示
dostufforandompositions的代码
public static bool doStuffOnRandomPositions(ref lattice A, ref IGenerator rr)
{
    position firstPos = new position(rr.Next(0, A.n_size),rr.Next(0, A.n_size),rr.Next(0, A.n_size));
    position secondPos = randomNeighbour(ref A, firstPos, ref rr);

    //checks the closest 3d neighbours indexer the lattice
    //Console.WriteLine("first:[{0},{1},{2}]\nsecond:[{3},{4},{5}]\n", firstPos.x, firstPos.y, firstPos.z, secondPos.x, secondPos.y, secondPos.z);

    //  get values at coordinates
    bool first = A.latticeArray[firstPos.x, firstPos.y, firstPos.z];
    bool second = A.latticeArray[secondPos.x,secondPos.y,secondPos.z];

    if (first == second) //don't bother if they are equal states
        return false;

    //  checks the energies in surroundings for an eventual spin switch
    int surrBefore = surroundCheck(ref A, firstPos, first) ; // - surroundCheck(ref A, secondPos, second));
    int surrAfter = surroundCheck(ref A, firstPos, !first) ; // - surroundCheck(ref A, secondPos, !second));

    if (surrAfter < surrBefore) //switch spin states if lower total energy
    {
        A.latticeArray[firstPos.x, firstPos.y, firstPos.z] = !first;
        A.latticeArray[secondPos.x, secondPos.y, secondPos.z] = !second;
        return true;
    }
    else if ((surrAfter == surrBefore) & latticeDistribution(ref rr))   //TEMPORARY
    {
        A.latticeArray[firstPos.x, firstPos.y, firstPos.z] = !first;        //TEMPORARY
        A.latticeArray[secondPos.x, secondPos.y, secondPos.z] = !second;    //TEMPORARY
        return true;
    }
    else
        return false;
} //FIX SWITCH PROBABILITIES