c# - 线程安全 Parallel.For c#

标签 c# multithreading for-loop parallel-processing

我是法语,很抱歉,首先对不起我的英语。

我在 visual studio 上有一个错误(索引超出范围)我只在 Parallel.For 上有这个问题,在 classic for 上没有。

我认为一个线程想要访问我的数组 [i] 而另一个线程也想要..

这是一个计算 Kmeans 聚类的代码,用于在文档之间建立链接(具有余弦相似度)。

更多信息:

  • IndexOutOfRange 在 similarityMeasure[i]=.....

  • 我有一台带 2 个处理器(12 个逻辑)的计算机

  • 使用经典 for 时,cpu 使用率为 9-14%,1 次迭代的时间 = 9 分钟..

  • 使用 parallel.for 时,cpu 使用率为 70-90% =p,1 次迭代的时间 =~1min30

  • 有时它在产生错误之前工作的时间更长

我的功能是:

    private static int FindClosestClusterCenter(List<Centroid> clustercenter, DocumentVector obj)
{
    float[] similarityMeasure = new float[clustercenter.Count()];
    float[] copy = similarityMeasure;
    object sync = new Object();

  Parallel.For(0, clustercenter.Count(), (i) =>      //for(int i = 0; i < clustercenter.Count(); i++)  Parallel.For(0, clustercenter.Count(), (i) =>  //
       {
                similarityMeasure[i] = SimilarityMatrics.FindCosineSimilarity(clustercenter[i].GroupedDocument[0].VectorSpace, obj.VectorSpace);

       });

    int index = 0;
    float maxValue = similarityMeasure[0];
    for (int i = 0; i < similarityMeasure.Count(); i++)
    {
        if (similarityMeasure[i] > maxValue)
        {
            maxValue = similarityMeasure[i];
            index = i;
        }

    }
    return index;
}

我的函数在这里调用:

do
            {
                prevClusterCenter = centroidCollection;
                DateTime starttime = DateTime.Now;

                  foreach (DocumentVector obj in documentCollection)//Parallel.ForEach(documentCollection, parallelOptions, obj =>//foreach (DocumentVector obj in documentCollection)
                   {

                       int ind = FindClosestClusterCenter(centroidCollection, obj);

                       resultSet[ind].GroupedDocument.Add(obj);

                   }
                TimeSpan tempsecoule = DateTime.Now.Subtract(starttime);
                Console.WriteLine(tempsecoule);
                //Console.ReadKey();
                InitializeClusterCentroid(out centroidCollection, centroidCollection.Count());
                centroidCollection = CalculMeanPoints(resultSet);
                stoppingCriteria = CheckStoppingCriteria(prevClusterCenter, centroidCollection);
                if (!stoppingCriteria)
                {
                    //initialisation du resultat pour la prochaine itération
                    InitializeClusterCentroid(out resultSet, centroidCollection.Count);
                }
            } while (stoppingCriteria == false);
            _counter = counter;
            return resultSet;

求余弦相似度:

 public static float FindCosineSimilarity(float[] vecA, float[] vecB)
        {
            var dotProduct = DotProduct(vecA, vecB);
            var magnitudeOfA = Magnitude(vecA);
            var magnitudeOfB = Magnitude(vecB);
            float result = dotProduct / (float)Math.Pow((magnitudeOfA * magnitudeOfB),2);
            //when 0 is divided by 0 it shows result NaN so return 0 in such case.
            if (float.IsNaN(result))
                return 0;
            else
                return (float)result;

        }

计算均值点:

 private static List<Centroid> CalculMeanPoints(List<Centroid> _clust)
        {
            for (int i = 0; i < _clust.Count(); i++)
            {
                if (_clust[i].GroupedDocument.Count() > 0)
                {
                    for (int j = 0; j < _clust[i].GroupedDocument[0].VectorSpace.Count(); j++)
                    {
                        float total = 0;
                        foreach (DocumentVector vspace in _clust[i].GroupedDocument)
                        {
                            total += vspace.VectorSpace[j];
                        }

                        _clust[i].GroupedDocument[0].VectorSpace[j] = total / _clust[i].GroupedDocument.Count();
                    }
                }
            }
            return _clust;
        }

最佳答案

FindCosineSimilarity 可能会有一些副作用,请确保它不会修改任何字段或输入参数。示例:resultSet[ind].GroupedDocument.Add(obj);。如果 resultSet 不是对本地实例化数组的引用,那么它是一个 side effect .

这可能会解决它。但仅供引用,您可以为此使用 AsParallel 而不是 Parallel.For:

similarityMeasure = clustercenter
      .AsParallel().AsOrdered()
      .Select(c=> SimilarityMatrics.FindCosineSimilarity(c.GroupedDocument[0].VectorSpace, obj.VectorSpace))
      .ToArray();

关于c# - 线程安全 Parallel.For c#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30523743/

相关文章:

c# - 从线程加速实时 Gui 更新

javascript - MVC 4 网站在 iPad 上非常慢

c# - 使用多个字段加入 linq 查询

c++ - 多线程时如何避免堆栈空间不足?

JavaScript 函数并不执行所有内容

c# - 如何在 ASP.NET ListView ItemTemplate 中返回 HTML?

php - 用户线程 : list in Gmail API not working with maxResults

c++ - 互斥作为类成员

javascript - 基本模数理解有问题

scala - 将 'for' 循环从 Java 重写为 Scala