Answers:
除了其他答案中提到的要点(难以证明操作是独立的,并且程序员是串行考虑的)之外,还需要考虑第三个因素:并行化的成本。
事实是,线程并行性具有与之相关的巨大成本:
创建线程非常昂贵:对于内核,启动线程与启动进程几乎相同。我不确定确切的费用,但我相信大约是10微秒。
通过互斥锁进行线程通信的代价很高:通常,这需要在每一侧进行系统调用,可能会使线程进入睡眠状态并再次唤醒它,这会导致延迟以及冷高速缓存和刷新的TLB。平均而言,获取和释放互斥锁大约需要一微秒。
到目前为止,一切都很好。为什么这对于隐式并行性是一个问题?因为隐式并行性最容易在小规模上证明。证明一个简单循环的两个迭代是彼此独立的是一回事,证明stdout
向数据库打印内容和向数据库发送查询是彼此独立的并且可以并行执行是完全不同的事情(数据库进程可能在管道的另一端!)。
也就是说,计算机程序可以证明的隐式并行性很可能无法利用,因为并行化的成本大于并行处理的优势。另一方面,编译器无法证明可以真正加速应用程序的大规模并行处理。只需考虑一下CPU在一毫秒内可以完成多少工作。现在,如果假设并行化要比串行程序快,那么并行程序必须能够在两次互斥调用之间使所有CPU繁忙几毫秒。这需要非常粗糙的并行度,几乎不可能自动证明。
最后,毫无例外,没有规则:在不涉及线程的情况下利用隐式并行机制是可行的,代码矢量化就是这种情况(使用SIMD指令集,例如AVX,Altivec等)。对于那些相对容易证明的小规模并行而言,这确实是最好的。
程序员是串行思考的,当前的语言是为了支持该模型而构建的。除了诸如Haskell Erlang之类的边缘语言外,语言(我不使用形容词“现代”)本质上是高级汇编,在这里我们仍然告诉计算机该做什么,何时做以及如何做。直到我们有了一个回声系统,在这里告诉计算机我们想要的结果是可用的为止,作为程序员,我们没有足够的能力充分利用多线程功能。
也就是说,这是不自然的……
don't have the patience
是比以前更准确的评估don't have the mental capacity
。在我的职业生涯中,我见过的懒惰程序员比愚蠢的程序员还多。不过,我很幸运,在大学的第一年,我就学习了边程序和面向对象的函数编程和细粒度并行编程。我怀疑许多程序员并不那么幸运,因此他们的思维过程受到了极大的限制。