我决定学习并发性,并希望了解两个不同进程的指令可以重叠的方式。两个进程的代码只是一个10迭代循环,在每次迭代中执行3条指令。我想出了一个问题,包括将X指令固定在一个点,然后在空间之间安装来自另一个进程的其他X指令,同时考虑到它们必须被排序(进程B的指令4必须总是在指令20之前)。
我编写了一个程序来计算这个数字,看看结果我发现解决方案是n组合k,其中k是在一个过程的整个循环中执行的指令数,因此对于10次迭代它将是30是n,n是k * 2(2个处理)。换句话说,n个固定的n个对象在空间中不适合n / 2而没有后者n / 2失去它们的顺序。
好的问题解决了。不,不是真的。我不知道为什么会这样,我明白组合的定义是,你可以用多少种方式从一组n中取k个元素,这样所有的组都是不同的,但你采用这些元素的顺序并不是'无所谓。在这种情况下,我们有n个元素,我们实际上是全部,因为所有指令都被执行(n C n)。
如果有人通过说明袋中有2k蓝色(A)和红色(B)物体来解释它并从袋中取出k个物体,那么当实际执行2k指令时,你仍然只接受k指令。你能否对此有所了解?
提前致谢。
答案 0 :(得分:6)
FWIW可以这样看:你有一个包含 k 蓝色和 k 红球的包。相同颜色的球是难以区分的(类似于同一过程/线程中的指令顺序是固定的限制 - 在现代处理器中不是这样,但现在让我们保持简单)。你可以用多少种不同的方式将球从球袋中拉出来?
我的组合技能非常生疏,但我的第一个猜测是
(2k!)
-----
2*k!
,根据Wikipedia,确实等于
(2k)
(k )
(抱歉,我不知道如何展示这个)。
对于 n 进程,可以通过在包中放入 n 不同颜色的球来推广。
更新:请注意,从严格意义上讲,这仅模拟了在单个处理器上执行不同进程的情况,因此所有进程的所有指令都必须在处理器级别进行线性排序。在多处理器环境中,几个指令可以同时执行。
答案 1 :(得分:2)
一般来说,我同意Péter的答案,但由于它似乎没有完全点击OP,所以这是我的镜头(纯粹从数学/组合的角度来看)。
您有两组30(k)指令,总共60(n)条指令。由于每组30必须保持有序,我们不需要跟踪每组中的哪条指令,只需跟踪指令来自哪一组。因此,我们有60个“插槽”,其中可以放置来自一组(例如,红色)的30条指令和来自另一组(例如,蓝色)的30条指令。
让我们首先将30条红色指令放入60个插槽中。有(60选择30)= 60!/(30!30!)方法(我们选择60个中的30个插槽用红色指令填充)。现在,我们仍然有30条蓝色指令,但我们只剩下30个开放式插槽。有(30选30)= 30!/(30!0!)= 1方式将蓝色指令放在剩余的插槽中。所以,总共有(60选30)*(30选30)=(60选30)* 1 =(60选30)方法。
现在,让我们假设您有3组(红色,绿色,蓝色)k指令,而不是2组30。您总共需要3k个插槽才能填充。首先,放置红色的:(3k选择k)=(3k)!/(k!(3k-k)!)=(3k)!/(k!(2k)!)。现在,将绿色的插入剩余的2k插槽:(2k选择k)=(2k)!/(k!k!)。最后,将蓝色的那些放入最后的k个槽中:(k选择k)= k!/(k!0!)= 1.总计:(3k选择k)*(2k选择k)*(k选择k) =((3k)!*(2k)!* k!)/(k!(2k)!* k!k!* k!0!)=(3k)!/(k!k!k!)。< / p>
作为进一步的扩展(虽然我不打算提供完整的解释):
答案 2 :(得分:1)
Péter的回答很好,但这并不能解释为什么并发很困难。那是因为现在越来越多的时候你有多个可用的执行单元(无论是内核,CPU,节点,计算机等等)。这反过来意味着指令之间重叠的可能性进一步增加;无法保证使用任何传统交错可以正确建模所发生的事情。
这就是为什么考虑正确使用信号量/互斥量以及为什么内存障碍很重要的原因。那是因为所有这些事情最终将真正讨厌的画面转变为更容易理解的东西。但由于互斥体减少了可能的执行次数,因此降低了整体性能和潜在效率。这绝对是棘手的,而这又是为什么如果你可以在不以其他方式交互的活动线程之间的消息传递方面工作呢?它更容易理解,同步更少更好。