标签: parallel-processing

了解VS2010 C#并行分析结果

我有一个程序有很多独立的计算,所以我决定并行化它.

我使用Parallel.For/Each.

双核机器的结果还可以 - 大多数时候CPU利用率约为80%-90%.但是,使用双Xeon机器(即8个内核),我只获得了大约30%-40%的CPU利用率,尽管该程序在并行部分上花费了相当多的时间(有时超过10秒),我看到它使用了与串行部分相比,这些部分中大约有20-30个线程.每个线程需要1秒以上才能完成,所以我认为它们没有理由不能并行工作 - 除非存在同步问题.

我使用了VS2010的内置分析器,结果很奇怪.即使我只在一个地方使用锁,分析器报告大约85%的程序时间用于同步(也是5-7%睡眠,5-7%执行,低于1%IO).

锁定的代码只是一个缓存(字典)get/add:

bool esn_found;
lock (lock_load_esn)
    esn_found = cache.TryGetValue(st, out esn);
if(!esn_found)
{
    esn = pData.esa_inv_idx.esa[term_idx];
    esn.populate(pData.esa_inv_idx.datafile);
    lock (lock_load_esn)
    {
        if (!cache.ContainsKey(st))
            cache.Add(st, esn);
    }
}
Run Code Online (Sandbox Code Playgroud)

lock_load_esn是Object类型的静态成员.
esn.populate使用单独的StreamReader为每个线程从文件中读取.

但是,当我按下同步按钮以查看导致最大延迟的原因时,我看到探查器报告的是作为功能入口线的线,并且不报告锁定的部分本身.
它甚至没有报告包含上述代码的功能(提醒 - 程序中唯一的锁定)作为阻塞配置文件的一部分,噪声级别为2%.当噪音水平为0%时,它会报告程序的所有功能,我不明白为什么它们被视为阻塞同步.

所以我的问题是 - 这里发生了什么?
85%的时间花在同步上怎么样?
如何找出程序中并行部分的实际问题?

谢谢.

更新:深入研究线程(使用极其有用的可视化工具)后,我发现大部分同步时间都花在等待GC线程完成内存分配上,并且由于通用数据结构调整大小操作需要频繁的分配.

我将不得不看看如何初始化我的数据结构,以便它们在初始化时分配足够的内存,可能避免GC线程的这种竞争.

我今天晚些时候会报告结果.

更新:看起来内存分配确实是问题的原因.当我在并行执行的类中使用所有词典和列表的初始容量时,同步问题更小.我现在只有大约80%的同步时间,CPU利用率达到70%(先前的峰值仅为40%左右).

我进一步钻进每个线程,发现现在很多调用GC分配用于分配不属于大字典的小对象.

我通过为每个线程提供一个预先分配的这类对象池来解决这个问题,我使用它而不是调用"new"函数.

所以我基本上为每个线程实现了一个单独的内存池,但是以非常粗糙的方式,这非常耗时,实际上并不是很好 - 我仍然需要使用很多新的来初始化这些对象,只有现在我全局执行一次,即使不得不增加池的大小,GC线程上的争用也会减少.

但这绝对不是我喜欢的解决方案,因为它不容易推广,我不想写自己的内存管理器.
有没有办法告诉.NET为每个线程分配预定义的内存量,然后从本地池中获取所有内存分配?

c# parallel-processing profiling visual-studio-2010

15
推荐指数
1
解决办法
1263
查看次数

在R中并行化矢量化函数的最简单方法是什么?

我有一个非常大的列表X和一个矢量化函数f.我想计算f(X),但如果我用一个核心来做这个将需要很长时间.我有(访问)48核服务器.并行计算的最简单方法是f(X)什么?以下不是正确的答案:

library(foreach)
library(doMC)
registerDoMC()

foreach(x=X, .combine=c) %dopar% f(x)
Run Code Online (Sandbox Code Playgroud)

上面的代码确实会对计算进行并行化f(X),但它会通过f单独应用于每个元素来实现X.这忽略了矢量化的性质,f并且可能会使事情变慢,而不是更快.而不是应用felementwise X,我想X分成合理大小的块并应用于f那些.

那么,我应该手动拆分X成48个相等大小的子列表然后f并行应用于每个子列表,然后手动将结果放在一起?或者是否有为此设计的包装?

如果有人想知道,我的具体用例就在这里.

parallel-processing r vectorization

15
推荐指数
3
解决办法
1682
查看次数

doRedis如何运作?

我一直在玩redis数据库R接口,以及foreachdoRedis并行后端.我有几个问题,帮助我更好地应用此工具:

  1. doMC,doSMP,doSnow等似乎都可以通过在同一台计算机上调用工作进程,从列表和要应用的函数传递它们,然后收集结果来工作.在doMC的情况下,工作人员共享内存.但是,对于数据库如何提供相同的功能,我有点困惑.
  2. 当我将另一台从属计算机添加到doRedis作业队列时(如本视频所示),整个doredis数据库是否被发送到从属计算机?或者每个奴隶只是在特定时刻所需的数据(即列表的一个元素和要应用的函数).
  3. 如何将其他数据和函数显式传递给doRedis作业队列,每个从站都需要执行它的计算?
  4. 使用doRedis和foreach时,是否还有其他"陷阱"可能不适用于其他并行后端?

我知道这是很多问题,但我一直遇到这样一种情况,即我对并行处理如何工作的有限理解阻碍了我实现它的能力.例如,我最近尝试在大型数据库上并行化计算,并发现自己将整个数据库传递到我的集群上的每个节点,这一操作完全破坏了我从并行化中获得的任何优势.

谢谢!

parallel-processing r cluster-computing redis r-doredis

15
推荐指数
1
解决办法
1569
查看次数

并行Linq查询优化

一段时间以来,我一直围绕没有副作用的方法构建我的代码,以便使用并行linq来加快速度.一路走来,我不止一次偶然发现懒惰的评估让事情变得更糟而不是更好,我想知道是否有任何工具可以帮助优化并行linq查询.

我问,因为我最近通过修改某些方法并AsParallel在某些关键位置加油来重构一些令人尴尬的并行代码.运行时间从2分钟下降到45秒,但从性能监视器可以清楚地看出,有些地方CPU上的所有内核都没有得到充分利用.在一些错误的启动后,我强制执行一些查询,ToArray并且运行时间进一步降低到16秒.减少代码的运行时间感觉很好,但它也有点令人不安,因为不清楚需要强制使用代码查询的位置ToArray.等到查询执行的最后一分钟不是最佳策略,但是根本不清楚代码中的哪些点需要强制某些子查询才能利用所有CPU内核.

因为它是我不知道如何正确胡椒ToArray或其他方法迫使linq计算执行,以获得最大的CPU利用率.那么优化并行linq查询是否有任何通用指南和工具?

这是一个伪代码示例:

var firstQuery = someDictionary.SelectMany(FirstTransformation);
var secondQuery = firstQuery.Select(SecondTransformation);
var thirdQuery = secondQuery.Select(ThirdTransformation).Where(SomeConditionCheck);
var finalQuery = thirdQuery.Select(FinalTransformation).Where(x => x != null);
Run Code Online (Sandbox Code Playgroud)

FirstTransformation,SecondTransformation,ThirdTransformation都是CPU绑定,并且在复杂性方面,他们有几个3x3矩阵乘法和一些if分支机构.SomeConditionCheck几乎是一张null支票.FinalTransformation是代码中CPU密集度最高的部分,因为它将执行一大堆线平面交叉,并检查这些交叉点的​​多边形包含,然后提取最接近线上某个点的交点.

我不知道为什么我放置的地方AsParallel减少了代码的运行时间.我现在已经达到了运行时间的局部最小值,但我不知道为什么.我偶然发现它只是运气不好.如果你想知道放置的地方AsParallel是第一行和最后一行.放在AsParallel其他地方只会增加运行时间,有时甚至会增加20秒.ToArray第一行还有隐藏的藏身之处.

c# linq parallel-processing plinq c#-4.0

15
推荐指数
2
解决办法
1万
查看次数

大型矩阵反演

我正在考虑采用大矩阵的逆矩阵,通常大小为1000 x 1000,但有时超过100000 x 100000(由于时间和内存,目前失败).我知道正常的情绪是"不要反过来,找其他方法去做",但目前这是不可能的.造成这种情况的原因是由于已经制作的软件需要使矩阵反转.(注意:我正在研究如何改变这种情况,但这需要很长时间)

目前我们正在使用数值重新复制的LU分解方法,我目前正在测试特征库.特征库似乎更稳定,速度更快,但我仍在测试阶段的准确性.我已经快速浏览了其他库,例如ATLAS和LAPACK,但尚未对这些库进行任何实质性测试.

似乎特征库不使用并发方法来计算逆(尽管对于逆分的LU分解部分也是如此),并且据我所知,ATLAS和LAPACK在此限制中是相似的.(我目前正在使用openMP测试特征的速度差异而没有.)

第一个问题是任何人都可以解释如何通过并行化优化矩阵求逆.我在这里发现了一篇关于矩阵求逆并行算法的文章,但我不明白.看来这篇文章谈到另一种方法?我也不确定scaLAPACK或PETSc是否有用?

第二个问题,我看了这个文章使用GPU来提高性能的,但我从来没有编码的GPU,因此不知道是什么人所要表达的,但在底部的图表看起来相当惊人.这怎么可能,以及如果要成为现实,我该如何开始实现这样的事情.

我也发现这篇文章,还有时间阅读它来理解,但它似乎很有希望,因为内存是我们软件的当前问题.

有关这些文章或一般问题的任何信息都会有很大帮助.如果这个问题看起来含糊不清,我再次道歉,如果有必要,我会尽量扩大.

parallel-processing concurrency linear-algebra matrix-inverse eigen

15
推荐指数
3
解决办法
9790
查看次数

高效的并行策略

我试图围绕并行策略.我想我理解每个组合器的作用,但每次我尝试使用超过1个核心时,程序都会大大减慢.

例如前一段时间我试图从~700个文档中计算直方图(以及来自它们的独特单词).我认为使用文件级粒度是可以的.随着-N4我获得1.70的工作平衡.然而,-N1它的运行时间比它的运行时间少一半-N4.我不确定这个问题究竟是什么,但我想知道如何决定何时/何时/如何并行化并获得一些理解.如何将其并行化,以便速度随核心而不是降低而增加?

import Data.Map (Map)
import qualified Data.Map as M
import System.Directory
import Control.Applicative
import Data.Vector (Vector)
import qualified Data.Vector as V
import qualified Data.Text as T
import qualified Data.Text.IO as TI
import Data.Text (Text)
import System.FilePath ((</>))
import Control.Parallel.Strategies
import qualified Data.Set as S
import Data.Set (Set)
import GHC.Conc (pseq, numCapabilities)
import Data.List (foldl')

mapReduce stratm m stratr r xs = let
  mapped = parMap stratm m xs
  reduced = r mapped `using` …
Run Code Online (Sandbox Code Playgroud)

parallel-processing haskell

15
推荐指数
1
解决办法
541
查看次数

使用R中的foreach读取全局变量

我试图在使用RStudio的16核CPU和64 GB RAM的Windows服务器上运行foreach循环.(使用doParallel包)

"worker"进程复制来自for循环外部的所有变量(通过在运行foreach循环时观察windows任务管理器中这些进程的实例化来观察),从而使每个进程使用的内存膨胀.我试图将一些特别大的变量声明为全局变量,同时确保这些变量也在foreach循环中读取,而不是写入,以避免冲突.但是,这些进程仍然会快速耗尽所有可用内存.

是否有一种机制可以确保"工作"进程不会创建某些"只读"变量的副本?比如声明这样的变量的具体方法?

parallel-processing foreach r

15
推荐指数
1
解决办法
8749
查看次数

并行化Scala的迭代器

请注意:这不是一个重复的问题,因为这个问题规定了所有方法Iterator,而不仅仅是mapflatMap.因此Future.traverse不是一个好的答案.

假设我有这个简单的陈述:

(1 to 100).toSet.subsets.find(f)
Run Code Online (Sandbox Code Playgroud)

它完美地运作.它是懒惰的,不会使用大量内存,只要找到一个元素就会返回.当您想并行化时,问题就开始了.你也许会说,这是斯卡拉,必须有.parIterator,但没有.

互联网上提出的解决方案是使用.grouped,但它不如我想要的那么好.为什么?

val it = (1 to 100).toSet.subsets.grouped(1000000).map(_.par.find(f)).flatten
if (it.hasNext) Some(it.next) else None
Run Code Online (Sandbox Code Playgroud)
  1. 使用更多的内存.我知道它仍然是O(1),但让我们在这里完美:)

  2. 它不是完全可并行化的(根据Amdahl定律).当.grouped消耗下一个百万元素块的迭代器时,除了一个线程之外的所有元素都在等待.如果迭代器消耗昂贵,则这尤其成问题.此外,还需要产生一组新线程来处理新块的开销.

  3. 生成更复杂/更长的代码(参见示例).如果Iterator.nextOption,它会缩短代码,但仍然.

尽管编程我自己的生产者 - 消费者模型(迭代器是生产者,线程是消费者)然后最终减少步骤,还有什么吗?

parallel-processing iterator scala scala-collections

15
推荐指数
1
解决办法
2215
查看次数

是否在R中使用detectCores函数来指定并行处理的核心数?

在它的帮助detectCores()说:

这不适合直接用于mclapply的mc.cores参数,也不适用于指定 makeCluster中的核心数.首先是因为它可能返回NA,其次是因为它没有给出允许的核心数.

但是,我已经看到了相当多的示例代码,如下所示:

library(parallel)
k <- 1000
m <- lapply(1:7, function(X) matrix(rnorm(k^2), nrow=k))

cl <- makeCluster(detectCores() - 1, type = "FORK")
test <- parLapply(cl, m, solve)
stopCluster(cl)
Run Code Online (Sandbox Code Playgroud)

where detectCores()用于指定其中的核心数makeCluster.

我的用例包括在我自己的多核笔记本电脑(OSX)上运行并行处理并在各种多核服务器(Linux)上运行它.因此,我不确定是否有更好的方法来指定内核数量,或者是否对于不使用的建议detectCores更多的是针对包含在广泛的硬件和操作系统环境中运行代码的开发人员.

总结如下:

  • 您是否应该使用detectCoresR中的函数来指定并行处理的核心数?
  • 检测到的和允许的核心之间的区别是什么?它们何时相关?

parallel-processing r

15
推荐指数
2
解决办法
8579
查看次数

多处理:仅使用物理内核?

我有一个foo消耗大量内存的功能,我希望并行运行几个实例.

假设我有一个带有4个物理内核的CPU,每个内核都有两个逻辑内核.

我的系统有足够的内存来容纳4个foo并行实例,但不是8个.而且,由于这8个内核中有4个是逻辑的,所以我也不希望使用所有8个内核可以提供超出使用4个物理内核的大量增益只要.

所以,我想运行foo在4个物理内核.换句话说,我想确保执行multiprocessing.Pool(4)(4是由于内存限制而在此计算机上可以容纳的函数的最大并发运行次数)将作业调度到四个物理内核(例如,不是两个物理核心及其两个逻辑后代的组合.

如何在python中做到这一点?

编辑:

我之前使用过代码示例,multiprocessing但我与库无关,所以为了避免混淆,我删除了它.

python linux parallel-processing python-multiprocessing

15
推荐指数
3
解决办法
9855
查看次数