- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我有一项迁移工作,完成后我需要验证目标数据。为了通知管理员验证成功/失败,我使用计数器比较数据库 1 中表 Foo 的行数与数据库 2 中表 Foo 的行数。
Database2 中的每一行都根据 Database1 中的相应行进行验证。为了加快这个过程,我使用了一个 Parallel.ForEach
循环。
我最初的问题是计数总是与我的预期不同。后来发现+=
和-=
操作不是线程安全的(不是原子的)。为解决此问题,我更新了代码以在计数器变量上使用 Interlocked.Increment
。这段代码打印出一个更接近实际计数的计数,但是,每次执行似乎都不同,它没有给出我期望的结果:
Private countObjects As Integer
Private Sub MyMainFunction()
Dim objects As List(Of MyObject)
'Query with Dapper, unrelevant to the problem.
Using connection As New System.Data.SqlClient.SqlConnection("aConnectionString")
objects = connection.Query("SELECT * FROM Foo") 'Returns around 81000 rows.
End Using
Parallel.ForEach(objects, Sub(u) MyParallelFunction(u))
Console.WriteLine(String.Format("Count : {0}", countObjects)) 'Prints "Count : 80035" or another incorrect count, which seems to differ on each execution of MyMainFunction.
End Sub
Private Sub MyParallelFunction(obj As MyObject)
Interlocked.Increment(countObjects) 'Breakpoint Hit Count is at around 81300 or another incorrect number when done.
'Continues executing unrelated code using obj...
End Sub
在用其他方法使增量线程安全进行一些实验后,我发现将增量包装在虚拟引用对象上的 SyncLock
中会得到预期的结果:
Private countObjects As Integer
Private locker As SomeType
Private Sub MyMainFunction()
locker = New SomeType()
Dim objects As List(Of MyObject)
'Query with Dapper, unrelevant to the problem.
Using connection As New System.Data.SqlClient.SqlConnection("aConnectionString")
objects = connection.Query("SELECT * FROM Foo") 'Returns around 81000 rows.
End Using
Parallel.ForEach(objects, Sub(u) MyParallelFunction(u))
Console.WriteLine(String.Format("Count : {0}", countObjects)) 'Prints "Count : 81000".
End Sub
Private Sub MyParallelFunction(obj As MyObject)
SyncLock locker
countObjects += 1 'Breakpoint Hit Count is 81000 when done.
End SyncLock
'Continues executing unrelated code using obj...
End Sub
为什么第一个代码片段没有按预期工作?最令人困惑的是断点命中计数给出了意想不到的结果。
我对 Interlocked.Increment
或原子操作的理解有缺陷吗?我不希望在虚拟对象上使用 SyncLock
,我希望有一种方法可以干净地做到这一点。
更新:
Any CPU
上以 Debug
模式运行示例。ThreadPool.SetMaxThreads(60, 60)
,因为我在某个时候查询 Access 数据库。这会导致问题吗?Increment
的调用是否会干扰 Parallel.ForEach
循环,迫使它在所有任务完成之前退出?更新 2(方法论):
objects.Count
,然后再继续 Parallel.ForEach
。Interlocked.Increment
替换为 SyncLock locker
和 countObjects += 1
。更新 3
我通过在新的控制台应用程序中复制我的代码并替换外部类和代码来创建 SSCCE。
这是控制台应用程序的 Main
方法:
Sub Main()
Dim oClass1 As New Class1
oClass1.MyMainFunction()
End Sub
这是 Class1
的定义:
Imports System.Threading
Public Class Class1
Public Class Dummy
Public Sub New()
End Sub
End Class
Public Class MyObject
Public Property Id As Integer
Public Sub New(p_Id As Integer)
Id = p_Id
End Sub
End Class
Public Property countObjects As Integer
Private locker As Dummy
Public Sub MyMainFunction()
locker = New Dummy()
Dim objects As New List(Of MyObject)
For i As Integer = 1 To 81000
objects.Add(New MyObject(i))
Next
Parallel.ForEach(objects, Sub(u As MyObject)
MyParallelFunction(u)
End Sub)
Console.WriteLine(String.Format("Count : {0}", countObjects)) 'Interlock prints an incorrect count, different in each execution. SyncLock prints the correct count.
Console.ReadLine()
End Sub
'Interlocked
Private Sub MyParallelFunction(ByVal obj As MyObject)
Interlocked.Increment(countObjects)
End Sub
'SyncLock
'Private Sub MyParallelFunction(ByVal obj As MyObject)
' SyncLock locker
' countObjects += 1
' End SyncLock
'End Sub
End Class
当将 MyParallelFunction
从 Interlocked.Increment
切换到 SyncLock
时,我仍然注意到相同的行为。
最佳答案
属性上的
Interlocked.Increment
总是会被破坏。实际上,VB 编译器将其重写为:
Value = <value from Property>
Interlocked.Increment(Value)
<Property> = Value
因此破坏了 Increment
提供的任何线程保证。将其更改为字段。 VB 会将作为 ByRef
参数传递的任何属性重写为类似于上述代码的代码。
关于c# - 为什么 Interlocked.Increment 在 Parallel.ForEach 循环中给出不正确的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20619553/
在 Oracle 中,PARALLEL 被广泛使用。提示 PARALLEL、PARALLEL(8) 和 PARALLEL(a,8) 有什么区别。如何选择最佳的查询提示? SELECT /*+ PARA
好的,我希望以前没有问过这个问题,因为在搜索中很难找到。 我查看了 F95 手册,但仍然觉得这很模糊: For the simple case of: DO i=0,99 END DO 我正
我有一个 C-shell 脚本,其中有一个名为 $hosts_string 的变量,格式为: host1,host2,...,hostN 我还有一个名为 $chrs_string 的变量,其形式为:
是否可以从由gnu parallel产生的脚本的多次运行中调用gnu parallel? 我有一个python脚本,可以运行100个顺序顺序迭代,并且在每次迭代中的某处,并行计算4个值(使用gnu p
我想在几个输入上运行几个长时间运行的进程。例如。: solver_a problem_1 solver_b problem_1 ... solver_b problem_18 solver_c pro
TParallel.&For 和 TParallel.For 之间有区别吗? 两者都可以在 Delphi 10 Seattle 中编译。那么我应该坚持哪一个呢? 最佳答案 TParallel.&For
我第一次使用 julia 进行并行计算.我有点头疼。所以假设我开始 julia如下:julia -p 4 .然后我为所有处理器声明 a 函数,然后将它与 pmap 一起使用还有@parallel fo
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 10年前关闭。 Improve this
我有一堆相互排斥的方法,因此可以并行运行。有这样做的好方法吗?到目前为止,我有以下两种实现方式,但我不确定是否应该选择其中一种。 使用 Parallel.For : Parallel.For(0, 2
我对并行运行脚本很感兴趣,并且我已经开始查看 GNU 并行工具,但是我遇到了一些麻烦。我的脚本 doSomething 有 3 个参数,我想在参数的不同值上并行运行脚本。我该怎么做? 我试过:para
我需要在多核(和多线程)机器上运行多个作业。我正在使用 GNU Parallel utility跨核心分配作业以加速任务。要执行的命令在名为“命令”的文件中可用。我使用以下命令运行 GNU Paral
我正在尝试使用如下两个输入运行 Python 脚本。我得到了大约 300 个这两个输入,所以我想知道是否有人可以建议如何并行运行它们。 单次运行看起来像: python stable.py KOG_1
每天我都必须更新一堆存储库,并在其中一些中执行另一个命令(来自 CARTON,Perl 模块依赖管理器)。我总是使用循环来执行此操作,但我想与 并行执行GNU 并行 如果可能,但我不太了解它的tuto
正如标题所说:@parallel 之间究竟有什么区别?和 pmap ?我的意思不是明显的一个是循环的宏,另一个适用于函数,我的意思是它们的实现究竟有什么不同,我应该如何使用这些知识在它们之间进行选择?
我有一些矩阵乘法运算。我想通过多个处理器并行执行这些操作。这可以使用 MPI(消息传递接口(interface))在高性能计算集群上完成。 同样,我可以使用多个辅助角色在云中进行一些并行化吗?有什么办
joblib模块提供了一个简单的帮助程序类,以使用多处理并行编写循环的循环。 这段代码使用列表推导来完成这项工作: import time from math import sqrt from job
我的问题是这样的one .但我想做一些不同的事情... 例如,在我的并行区域内,我想在 4 个线程上运行我的代码。当每个线程进入 for 循环时,我想在 8 个线程上运行我的代码。像 #pramga
我正在尝试使用 ipython 并行库中的并行计算。但是我对此知之甚少,而且我发现很难从对并行计算一无所知的人那里阅读该文档。 有趣的是,我发现的所有教程都只是重复使用文档中的示例,并使用相同的解释,
我的项目结构看起来像 Root + subproj1 + subproj2 在每个子项目中定义了自己的任务 run(){}。 我想要做的是从 Root 项目的运行任务并行运行 :subpro
我有一个 Foo ID 的列表。我需要为每个 ID 调用一个存储过程。 例如 Guid[] siteIds = ...; // typically contains 100 to 300 elemen
我是一名优秀的程序员,十分优秀!