所以它看起来像多核,所有相关的复杂功能都存在.我正在计划一个肯定会受益于并行性的软件项目.问题是我编写并发软件的经验很少.我在大学学习并很好地理解了概念和理论,但是从学校开始就没有掌握在多个处理器上运行软件的有用经验.
所以我的问题是,开始使用多处理器编程的最佳方法是什么? 我熟悉C/C++中的Linux开发和Mac OS X上的Obj-C,几乎没有Windows经验.此外,我计划的软件项目将需要FFT并且可能需要对大量数据进行浮点比较.
有OpenCL,OpenMP,MPI,POSIX线程等......我应该从哪些技术开始?
以下是我正在考虑的几个堆栈选项,但不确定他们是否会让我尝试实现我的目标:
在此先感谢您的帮助.
我一直在研究.Net 4.0中一些新的并行功能的实用性.
说我有这样的代码:
foreach (var item in myEnumerable)
myDatabase.Insert(item.ConvertToDatabase());
Run Code Online (Sandbox Code Playgroud)
想象一下myDatabase.Insert正在执行一些工作来插入SQL数据库.
从理论上讲,你可以写:
Parallel.ForEach(myEnumerable, item => myDatabase.Insert(item.ConvertToDatabase()));
Run Code Online (Sandbox Code Playgroud)
并自动获得利用多个内核的代码.
但是如果myEnumerable只能通过一个线程进行交互呢?Parallel类是否会通过单个线程进行枚举,并仅将结果分派给循环中的工作线程?
如果myDatabase只能由一个线程进行交互怎么办?在循环的每次迭代中建立数据库连接肯定不会更好.
最后,如果我的"var item"碰巧是UserControl或者必须在UI线程上与之交互的东西呢?
我应该采用什么设计模式来解决这些问题?
在我处理真实世界的应用程序时,切换到Parallel/PLinq/etc并不容易.
随着软件越来越多并发,您如何使用单元测试来处理类型的核心行为(不是并行行为,只是核心行为)?
在过去的好时光中,你有一个类型,你打电话给它,你检查了它返回的内容和/或它所调用的其他内容.
现在,你调用一个方法,实际的工作计划在下一个可用的线程上运行; 你不知道什么时候它会真正启动并调用其他东西 - 更重要的是,其他东西也可能是并发的.
你怎么处理这个?你抽象/注入并发调度程序(例如抽象任务并行库并在单元测试中提供假/模拟)?
您遇到了哪些资源帮助了您?
编辑
我编辑了这个问题,强调测试类型的正常行为(忽略用于利用多核的任何并行机制,例如TPL)
parallel-processing concurrency unit-testing parallel-extensions
我正在使用Python多处理为每个进程生成一个临时输出文件.它们的大小可以是几GB,我可以制作几十个.这些临时文件需要合并以形成所需的输出,这是证明是瓶颈(和并行杀手)的步骤.是否有一个Linux工具可以通过修改文件系统元数据而不是实际复制内容来创建连接文件?只要它适用于我可以接受的任何Linux系统.但是文件系统特定的解决方案不会有太大帮助.
我不是OS或CS的训练,但在理论上似乎应该有可能创造一个新的inode并复制了从我想从复制文件的inode的inode的指针结构,然后取消与这些索引节点.是否有任何实用程序可以做到这一点?考虑到经过深思熟虑的unix实用程序的过多,我完全可以预料到它,但找不到任何东西.因此我的问题是关于SO的.文件系统位于块设备上,实际上是硬盘,以防这些信息很重要.我没有信心自己编写这个,因为我以前从未做过任何系统级编程,所以任何指针(对C/Python代码的反转)都会非常有用.
我经常最终得到几个嵌套foreach循环,有时候在编写一般函数时(例如对于一个包),没有明显的并行化级别.有没有办法完成下面的模型描述?
foreach(i = 1:I) %if(I < J) `do` else `dopar`% {
foreach(j = 1:J) %if(I >= J) `do` else `dopar`% {
# Do stuff
}
}
Run Code Online (Sandbox Code Playgroud)
此外,有没有办法检测并行后端是否已注册,以便我可以避免收到不必要的警告消息?在CRAN提交之前检查包并且不打扰在单核计算机上运行R的用户时,这将非常有用.
foreach(i=1:I) %if(is.parallel.backend.registered()) `dopar` else `do`% {
# Do stuff
}
Run Code Online (Sandbox Code Playgroud)
谢谢你的时间.
编辑:非常感谢您对核心和工作人员的所有反馈,并且你是对的,处理上述示例的最佳方法是重新考虑整个设置.我更喜欢下面这个triu想法,但它基本上是相同的.它当然也可以tapply像Joris建议的那样平行完成.
ij <- expand.grid(i=1:I, j=1:J)
foreach(i=ij$I, j=ij$J) %dopar% {
myFuction(i, j)
}
Run Code Online (Sandbox Code Playgroud)
然而,在我试图简化引起这个线程的情况时,我遗漏了一些关键的细节.想象一下,我有两个功能analyse,并batch.analyse和最好的水平,在并行依据的值可能是不同的n.replicates和n.time.points.
analyse <- function(x, y, n.replicates=1000){
foreach(r = 1:n.replicates) %do% {
# Do stuff with …Run Code Online (Sandbox Code Playgroud) 我使用Parallel.Foreach来填充外部ConcurrentBag.我也尝试使用一个常见的List,一切正常.
我很幸运或者我错过了ConcurrentBag的特殊范围?
Haskell提供了一个par组合器,它将一个"火花"排队,以便与当前线程并行进行可能的评估.它还提供了一个pseq组合器,它强制评估纯代码以特定顺序发生.
Haskell似乎没有提供的是产生几个火花的方法,然后等待它们全部完成.使用显式并发实现这一点非常简单,但纯粹的火花似乎是不可能的.
在某种程度上,这可能是因为火花的预期用例.它们似乎是为投机评估而设计的.也就是说,做可能需要但可能不需要的工作.因此,火花仅在核心上运行,否则它们是空闲的.
但是,这不是我的用例.我知道很多结果,事实上很快就会需要.如果我在火花爆发之前开始尝试处理结果,我将再次以一堆失败的火花结束单线程.
当然,par 等待火花完成,它不会达到任何并行性!但如果有某种方法可以产生几个火花然后等待它们全部完成,那将是非常有用的.我找不到任何方法可以做到这一点.
有没有人有任何有用的建议?(显然,除了"使用显式并发"之外).
我正在运行R中的termstrc收益率曲线分析包,其中包含5个不同国家的10年每日债券价格数据.这是高度计算密集型的,在标准的lapply上每个国家需要3200秒,如果我在2009 i7 mac上使用foreach和%dopar%(使用doSNOW),使用所有4个核心(8个超线程)我将其归结为850秒 每次我添加一个国家(计算国家间利差)时我都需要重新运行这种分析,而且我还有19个国家可以使用,未来会有更多的信用收益曲线.所花费的时间开始看起来像一个主要问题.顺便说一句,有问题的termstrc分析函数在R中访问,但用C语言编写.
现在,我们是一个12人的小公司(预算有限),全部配备8GB内存,i7个电脑,其中至少有一半用于平凡的文字处理/电子邮件/浏览风格任务,即使用5%最大的表现.它们都使用千兆位(但不是10千兆位)以太网联网.
我可以使用MPI对其中一些未充分利用的PC进行集群,并对它们进行R分析吗?网络会受到影响吗?收益率曲线分析函数的每次迭代大约需要1.2秒,因此我假设如果并行处理的粒度是将整个函数迭代传递给每个集群节点,那么与千兆位以太网滞后相比,1.2秒应该是非常大的?
可以这样做吗?怎么样?那会对我的同事产生什么影响呢.我在给他们的机器征税时能否继续阅读他们的电子邮件?
我注意到Open MPI似乎不再支持Windows,而MPICH似乎也是如此.如果有的话,你会用哪个?
也许在每台PC上运行一个Ubuntu虚拟机?
我正在使用Surefire插件在Selenium Grid上运行Selenium测试来执行测试.就我的测试分类而言,我有几个类,其中一些有1个测试,还有一个多个测试.
所以在我的网格上我有30个chrome web驱动程序,我想并行执行所有类中的所有测试.
我已经阅读了如何使用parallel我设置的参数执行此操作:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<includes>
<include>${testSuite}</include>
</includes>
<parallel>all</parallel>
<useSystemClassLoader>false</useSystemClassLoader>
<perCoreThreadCount>false</perCoreThreadCount>
<threadCount>20</threadCount>
<browser>${browser_type}</browser>
</configuration>
</plugin>
Run Code Online (Sandbox Code Playgroud)
但是,这似乎并没有填补我可用的所有Chrome网络驱动程序.
如果我然后使用forkCount,如:
<forkCount>20</forkCount>
<reuseForks>true</reuseForks>
Run Code Online (Sandbox Code Playgroud)
然后,当测试执行首次启动时,所有Web驱动程序都会被填充,但它会快速开始丢弃并一次执行一个.
所以我的问题:
谢谢.
我试图并行for循环(一个尴尬的并行以前问这里)和解决这个实现适合我的参数:
with Manager() as proxy_manager:
shared_inputs = proxy_manager.list([datasets, train_size_common, feat_sel_size, train_perc,
total_test_samples, num_classes, num_features, label_set,
method_names, pos_class_index, out_results_dir, exhaustive_search])
partial_func_holdout = partial(holdout_trial_compare_datasets, *shared_inputs)
with Pool(processes=num_procs) as pool:
cv_results = pool.map(partial_func_holdout, range(num_repetitions))
Run Code Online (Sandbox Code Playgroud)
我需要使用代理对象(在进程之间共享)的原因是共享代理列表datasets中的第一个元素,它是一个大对象列表(每个大约200-300MB).此datasets列表通常包含5-25个元素.我通常需要在HPC群集上运行此程序.
这是一个问题,当我用32个进程和50GB内存运行这个程序(num_repetitions = 200,数据集是10个对象的列表,每个250MB)时,我甚至没有看到16倍的加速(32并行)流程).我不明白为什么 - 任何线索?任何明显的错误,或错误的选择?我在哪里可以改进这个实现?任何替代品?
我确信之前已经讨论过这个问题,原因可能多种多样,而且非常具体,因此我要求你提供2美分.谢谢.
更新:我使用cProfile进行了一些分析以获得更好的想法 - 这是一些信息,按累计时间排序.
In [19]: p.sort_stats('cumulative').print_stats(50)
Mon Oct 16 16:43:59 2017 profiling_log.txt
555404 function calls (543552 primitive calls) in 662.201 seconds
Ordered by: cumulative time
List reduced from 4510 to 50 …Run Code Online (Sandbox Code Playgroud)