为什么程序需要特定数量的最小CPU内核?


55

当在内核数少于N的CPU上运行时,是否可以编写无法正常工作的代码(或完整的软件,而不是一段代码)?没有显式检查并故意失败:

如果(noOfCores <4)则没有故意运行

我正在查看游戏的最低系统要求(Dragon Age:Inquisition),它规定了至少四核CPU。许多玩家表示,它不能在两核CPU上运行,甚至不能在具有两个物理核和两个逻辑核的Intel Core i3上运行。而且这不是计算能力的问题。

据我了解,操作系统无法将线程与CPU完全隔离开来。

只是为了清除事情:

不是在问:“我可以从代码中找出CPU内核的数量,并故意失败吗?” ...这样的代码是不正确的(迫使您购买更昂贵的CPU来运行程序-无需计算能力)。我要问的是,您的代码具有四个线程,并且当两个线程在同一物理核心上运行时会失败(而无需显式检查系统信息并有意地失败)

简而言之,是否可以有需要多个核的软件,而又不需要来自多个核的额外计算能力?它仅需要N个单独的物理核心。


11
如果您仔细阅读了我的问题,您会发现他们不是在问同样的事情。
uylmz 2015年

21
由于可以获取内核数,因此可以将其与N进行比较,并且如果该比较结果为true,则代码可以执行所需的所有操作,包括但不限于以未声明的方式进行操作。你有什么问题?

3
您确定问题确实与内核数量直接相关吗?也许上述游戏仅部分基于(至少正确地)由CPU提供的至少具有4个内核的功能?
mgoeminne 2015年

25
请注意,“最低系统要求”通常是“以可接受的性能运行的最低系统要求”,尤其是在游戏中。从理论上讲,《龙腾世纪》很有可能在单个核心盒上运行,但是如果这样做,它将显示大量帧丢失。因此,他们需要这样数量的内核,而不是强迫您购买硬件,而是避免低端硬件用户对质量提出投诉。

3
@Sebb:我想您正在做些事情:如果4个物理核心确实与拥有更多缓存然后2个物理/ 4逻辑相关,那么游戏自然会在2x2机器上窒息而没有达到其处理能力限制,因为它缺少所有缓存时间。测试将是找到具有2x2内核和高速缓存负载,或4内核和很少高速缓存的CPU,然后看看会发生什么。
史蒂夫·杰索普

Answers:


45

粗心使用核心亲和力可能“偶然”地做到这一点。考虑以下伪代码:

  • 启动线程
  • 在该线程中,找出它在哪个内核上运行
  • 将其CPU关联性设置为该内核
  • 开始做一些计算密集的事情/永远循环

如果在双核CPU上启动其中四个,则核心亲和力设置可能出了点问题,或者最终导致两个线程占用了可用内核,而两个线程却从未调度。它从未明确询问总共有多少个内核。

(如果您有长时间运行的线程,则设置CPU亲和力通常可以提高吞吐量)

游戏公司无缘无故地“强迫”人们购买更昂贵的硬件的想法不太合理。它只会失去他们的客户。

编辑:这篇文章现在有33票赞成票,这是相当多的,因为它是基于有根据的猜测!

似乎人们已经使DA:I糟糕地在双核系统上运行:http : //www.dsogaming.com/pc-performance-analyses/dragon-age-inquisition-pc-performance-analysis/该分析提到如果打开超线程,情况会大大改善。鉴于HT不再添加任何指令发布单元或缓存,它仅允许一个线程运行而另一个线程处于缓存停顿状态,这强烈表明它纯粹与线程数链接。

另一位张贴者声称,更改图形驱动程序是可行的:http : //answers.ea.com/t5/Dragon-Age-Inquisition/Working-solution-for-Intel-dual-core-CPUs/td-p/3994141;鉴于图形驱动程序往往是浮渣和恶棍的可怜蜂巢,这不足为奇。如果从QUAKE.EXE调用,则一组臭名昭著的驱动程序具有“正确和慢速”与“快速不正确”模式。对于不同数量的视在CPU,驱动程序的行为完全可能不同。也许(回到推测)使用了不同的同步机制。滥用自旋锁

“错误使用锁定和同步原语”是非常非常常见的错误来源。(我在写这篇文章时应该在工作中看到的错误是“如果在完成打印作业的同时更改打印机设置,则会崩溃”)。

编辑2:评论中提到OS试图避免线程匮乏。请注意,游戏可能具有自己的内部准调度程序,用于将工作分配给线程,并且图形卡本身(实际上是其自身的多任务系统)中将存在类似的机制。其中之一可能发生错误或它们之间的相互作用的可能性很高。

www.ecsl.cs.sunysb.edu/tr/ashok.pdf(2008)是有关如何更好地调度图形卡的研究生论文,其中明确提到它们通常使用先到先服务的调度方式,该方式易于实现。非抢先系统。情况有所改善吗?可能不是。


1
是的,回答这个问题有两个部分:CPU亲和力允许一个人编写一些代码,这将使这成为Windows中的技术要求,替代的答案是实时系统肯定会需要这些东西。+1是唯一提及CPU亲和力的人,这实际上是此处所问问题的最可能元凶。
吉米·霍法

3
如果将亲和力设置为当前核心,会出什么问题?使用抢占式多任务处理时,调度等待线程,除非当前线程具有最大可能的优先级(Windows中为“实时”)。我会看到另一种情况:4个线程中的每个线程都分配有1,2,4,8的静态定义的亲和力,在这种情况下,后两个线程将永远不会被调度(尽管我不确定是否将亲和力设置为有效零将成功)。
罗斯兰

@Ruslan也许试图设置无效的亲和力会首先使应用程序崩溃?
罗安2015年

1
@Luaan好,这不是危险操作导致崩溃。我所期望的最大是操作系统返回的错误。我刚刚检查过,在Linux中,我收到“无效参数”错误。不知道Windows会怎么说。
Ruslan 2015年

@Ruslan肯定十年来,每个主要的操作系统都包含避免线程匮乏的代码(通常是在线程运行时间不够长之后提高其优先级)。
Voo

34

可能需要有4个内核,因为应用程序在并行线程中运行四个任务,并期望它们几乎同时完成。

当每个线程由一个单独的内核执行并且所有线程都具有完全相同的计算工作量时,它们很有可能(几乎不能保证)大致同时完成。但是,当两个线程在一个内核上运行时,由于内核将始终在两个线程之间切换上下文,因此计时的可预测性将大大降低。

由于意外的线程定时而发生的错误称为“ 竞争条件 ”。

在游戏开发的背景下,存在这种问题的一种可能的架构可能是通过不同的CPU线程实时模拟游戏的不同功能的架构。当每个功能都在自己的内核上运行时,它们都将以大致相同的速度进行仿真。但是,当两个功能在一个内核上运行时,两者的仿真速度仅是游戏世界其余部分的一半,这可能会导致各种奇怪的行为。

请注意,依赖于按特定时间运行的独立线程的软件体系结构非常脆弱,这表明对并行编程的理解很差。几乎所有多线程API中都有可用的功能,可以显式同步线程以防止此类问题。


11
但是任何游戏都依赖于能够及时完成下一帧的所有计算以合理的频率渲染的脆弱性。即使您的4个线程正确同步,也可能无法及时渲染,并且在计算正确但由于滞后和卡顿而无法玩的游戏中也没有任何好处。
2015年

1
@无用:这不是真的。例如,您可以缓冲帧或模拟数据以隐藏任何卡顿现象,并且并发设计更加一致。在X时间内完成所有处理并要求该处理的确切同步是不同的事情。
DeadMG

23
“依赖于在特定时间运行的独立线程的软件体系结构非常脆弱”,这就是为什么我无法想象一款游戏根本不能在2个内核上运行,而是可靠地在4个内核上运行的原因。即使使用4核,时序也将无法预测,因此即使不那么频繁,竞争条件也会发生。
svick

8
@svick当然。但是这个问题问“有可能吗?” 不是“理智吗?”
user253751'1

5
任何带有这种“竞争条件”的代码都会被破坏,无论您在其上运行了多少个内核。(特别是因为绝对不能保证系统上还运行着其他什么。)我非常怀疑这是原因,因为即使在
六核

16

这些“最低要求”不太可能代表游戏无法运行的程度。它们更有可能代表某些东西,低于该值游戏将无法以令人满意的性能运行。没有哪家游戏公司愿意处理许多抱怨性能糟糕的客户,即使他们在技术上可以运行在单个核心1 Ghz盒子上运行时,却表现糟糕。因此,他们可能故意设计成在内核数量少于使它们可接受的性能的盒子上严重失效。

游戏性能的一项重要指标是帧速率。通常,它们以每秒30或60帧的速度运行。这意味着游戏引擎必须在固定的时间内从游戏状态渲染当前视图。要达到60 fps,它仅需要16毫秒以上。具有高端图形的游戏受CPU的限制很大,因此在尝试提高质量(这需要更多时间)与保持此时间预算之间存在巨大的取舍。因此,每一帧的时间预算非常紧张。

由于时间预算紧张,因此开发人员理想地希望独占访问一个或多个内核。他们还可能希望能够专门在一个核心中完成渲染工作,因为这是在该时间预算上必须完成的工作,而其他工作(例如计算世界状态)则发生在一个单独的过程中,而不会侵入。

从理论上讲,您可以将所有这些都塞进一个核心中,但是随后一切都会变得困难得多。突然,您必须确保所有游戏状态的东西发生得足够快,并允许您进行渲染。您不能仅仅使它们成为两个软件线程,因为无法让操作系统理解“无论线程B做什么,线程A必须在16毫秒内完成X的工作量”。

游戏开发商对您购买新硬件的兴趣为零。他们具有系统要求的原因是,支持低端机器的成本是不值得的。


虽然这是事实,但您可能会购买到双核硬件,该双核硬件足够强大,可以在给定的时间内实现比最低规格中所述的四核硬件更大的性能。为什么供应商不将这种硬件列为可接受的决定,而这种决定只会使他们失去销售?
Jules

4
要比较的不是2核还是4核。它实际上是1个内核与3个内核,因为图形驱动程序和DPC几乎固定了CPU#0。如果您在典型的现代游戏的作业系统中为CPU过度订购了几种任务,那么也会对缓存和迁移产生重大影响。之所以有此要求,是因为Frostbite(DA:I的引擎)是从头开始设计的,并且经过非常仔细的调整,需要特定数量的内核。
Lars Viklund

6
@LarsViklund听起来您比这里的其他人都知道更多的细节。您是否考虑过将答案组合在一起?

1
“这些“最低要求”不太可能代表游戏无法运行的水平。更有可能的是,这些“最低要求”代表游戏不能以可接受的性能运行。英特尔的G3258是一款功能非常强大的双核处理器,已被游戏玩家广泛使用,能够运行与《龙腾世纪审判》相同或更多的资源密集型游戏,但是许多玩家报告说游戏无法在其上运行。
uylmz 2015年

2
@Reek我怀疑最终用户是否可以轻易分辨出某个特定游戏与另一个游戏相比需要占用多少资源。
弄死了机器人2015年

9

三个永不休眠的实时线程和另一个线程。如果内核少于四个,则第四个线程将永远不会运行。如果第四个线程需要与一个实时线程进行通信以使实时线程完成,则代码将以少于四个内核完成。

显然,如果实时线程正在等待不允许它们进入睡眠状态的内容(例如自旋锁),则程序设计人员会搞砸了。


1
可以说,当用户应用程序首先请求实时线程时,设计人员就搞砸了:D
Luaan 2015年

2
我做完了 五百万行代码。一种情况下使用约300行。实时线程将大部分时间都花在等待输入上,因此它可以为输入加时间戳,并将其交给优先级较低的线程。
2015年

2
@Luaan对于大多数应用程序,我都会同意您的观点,但是游戏和嵌入式应用程序是不同的野兽。在这两种情况下,大多数人都希望与其他并发应用程序配合使用,以提高性能。
reirab 2015年

尽管它不是特别有效,但这种情况不会导致任何死锁-优先级倒置将解决该问题(假设过去十年中任何主要OS中的任何中途调度程序都如此)
Voo 2015年

2
@Joshua > Windows不知道什么是优先级倒置。什么?support.microsoft.com/kb/96418msdn.microsoft.com/en-us/library/windows/desktop/ms684831.aspx。同样,优先级倒置是描述问题的术语,而不是解决方案(@Voo)。
鲍勃

3

首先,软件线程与硬件线程无关,并且经常混杂在一起。软件线程是一段代码,可以在流程上下文中自己调度和运行。硬件线程主要由OS管理,并在谈论常规程序时调度到处理器的核心。这些硬件线程是根据负载分配的。硬件线程分派器的行为或多或少类似于负载均衡器。

但是,当涉及到游戏,尤其是高端游戏时,有时硬件线程是由游戏本身管理的,或者游戏会指示硬件线程分派器该怎么做。这是因为每个任务或一组任务的优先级都不像正常程序中那样。因为龙腾时代来自使用高端游戏引擎的高端游戏工作室,所以我可以想象它使用“手动”分发,然后内核数成为最小的系统要求。当我向只有1个或2个内核的机器上运行的第3个物理内核发送一段代码时,任何程序都会崩溃。


这个。请记住,说“核不检查”意味着公司正在以特定方式生产其软件产品,以迫使用户购买更昂贵的硬件(这是不明智的)。
uylmz 2015年

2
只要存在PC游戏,就存在这些问题。最初我们有486dx和486sx,后来是MMX和非MMX Pentium,核心和非核心,今天我们有了n核心要求。这就是控制台仍然存在的原因之一。
dj bazzie wazzie 2015年

4
您对自己负责CPU调度的游戏有参考吗?据我所知,在Windows下这是不可能直接实现的,至少不会以您建议的方式失败。
Jules

2
@djbazziewazzie实际上Windows确实提供了一个API来做到这一点,即设置一个线程以始终使用相同的内核;这称为线程关联性,它不允许您手动选择哪段代码在何时何地运行,并且不会导致您所建议的系统故障(系统将忽略将关联性设置为不存在的核心的请求,并且。只是不停的线程调度到任何核心可用时我敢肯定这是ID技术的使用,并且它并没有真正达到“管理硬件线程本身。”
朱尔斯

1
@djbazziewazzie您似乎还误解了Grand Central Dispatch的观点,该观点并不能使开发人员更好地控制将代码调度到内核的方式。实际上,它的目的恰恰相反:从应用程序手中选择要创建多少个线程以及应该在哪个线程上运行哪个代码,以便可以在系统级针对可用硬件进行优化。依赖于一定数量的内核正是GCD旨在避免的问题。
Jules

1

由于可以使用虚拟化来拥有比物理化更多的虚拟核,并且该软件不会知道它在虚拟化上运行,而是认为它确实具有许多物理核,因此我想说这样的软件是不可能的。

也就是说,不可能编写总是在少于N个内核上停止的软件。

正如其他人指出的那样,存在可以潜在地检查的软件解决方案,尤其是当N个进程在<N个处理器上运行时,如果所使用的OS和代码对竞争状况的保护很小。真正的窍门是代码,当您拥有少于N个处理器时,代码将失败,但是当您拥有N个处理器但具有可将工作分配给少于N个处理器的操作系统时,代码不会失败。


1

可能有三个线程在做某事(生成背景或生成NPC运动)并将事件传递给第四线程,这四个线程应该聚合/过滤事件并更新视图模型。如果第四个线程没有获得所有事件(因为它不是在内核上安排的),则视图模型将无法正确更新。这可能只是偶尔发生,但这些核心需要随时可用。这可能可以解释为什么您一直没有看到很高的CPU使用率,但是游戏仍然无法正常运行。


1
在这种情况下,当计划运行后台服务时,游戏也会随机失败,这在大多数PC上都是很常见的。
Jules

1

我认为约书亚(Joshua)正在朝着正确的道路前进,但这并不是结论。

假设您有一个架构,其中编写了三个线程以尽其所能-当他们完成自己正在做的事情时,便会再次执行它。为了保持性能,这些线程不会释放任何控制权-他们不想冒Windows任务计划程序滞后的风险。只要有4个或更多的内核,它就可以正常工作,如果没有,它就会严重失败。

总的来说,这将是糟糕的编程,但是游戏又是另一回事-当您面临在所有硬件劣等的设计,在足够好的硬件之上的优等设计或在劣等硬件上的失败之间做出选择时,游戏开发者通常会选择需要硬件。


通常不可能编写不会放弃对其他线程的控制的线程。所有现代的非RTOS操作系统都使用抢占式多任务处理,这有意使(用户模式)线程无法释放对给定内核的控制。当然,内核线程是另一回事。
reirab

@reirab提升它的优先级。
罗伦·佩希特尔

@Loren不会改变调度程序仍会死的事实,这意味着您必须与其他具有相同优先级的线程共享时间,并且调度程序会提高饥饿线程的优先级。您不能在普通的操作系统上做到这一点,即使可以,游戏当然也不是这样做的可接受的应用程序。
VOO

1

Is it possible to write code (or complete software, rather than a piece of code) that won't work properly when run on a CPU that has less than N number of cores?

绝对。实时线程的使用将很好地说明这种情况,在这种情况下,不仅可能,而且是完成任务的理想方式(通常是唯一正确的方式)。但是,实时线程通常仅限于OS内核,通常用于驱动程序,这些驱动程序需要能够保证某种硬件事件在定义的一段时间内得到处理。在普通的用户应用程序中您不应该具有实时线程,而且我不确定在Windows用户模式的应用程序中甚至可能有实时线程。通常,操作系统使精确地从用户土地上执行此操作成为不可能,因为它确实允许给定的应用程序接管系统的控制权。

关于用户土地应用程序:您认为检查给定数量的线程以运行必然是恶意的,这一假设是不正确的。例如,您可能有2个长期运行的,性能密集型任务,它们本身需要一个核心。无论CPU内核的速度如何,与其他线程共享一个内核可能会导致严重的性能下降,这是由于缓存抖动以及线程切换所引起的通常的惩罚(相当可观的)所致。这是完全合理的,特别是对于游戏而言,将每个线程设置为仅在每个特定内核上具有亲和力,然后将所有其他线程设置为在这两个内核上不具有亲和力。为了做到这一点,尽管


1

如果线程数超过内核数,则任何使用自旋锁且具有明显数量的锁争用的代码都将执行得非常糟糕(在某种程度上,对于游戏之类的应用程序,您可以说“不起作用”)。

假设有一个生产者线程将任务提交到服务4个消费者线程的队列。只有两个核心:

生产者试图获取自旋锁,但是它由运行在另一个核心上的消费者持有。当生产者在旋转时,这两个核心正在同步运行,等待锁被释放。这已经很糟糕了,但还没有达到预期的程度。
不幸的是,使用者线程在其时间范围的尽头,因此它被抢占,并计划了另一个使用者线程。它试图获取该锁,但是当然会采用该锁,因此现在两个内核正在旋转并等待不可能发生的事情。
生产者线程到达其时间片的末尾并被抢占,另一个消费者唤醒。同样,两个使用者都在等待释放锁,而这不会在再经过两个时间段之前发生。
[...]最终,持有自旋锁的消费者释放了锁。任何在另一个核心上旋转的人都会立即使用它。这是另一个使用方线程,有75%的机会(3比1)。换句话说,生产者处于停滞状态的可能性为75%。当然,这也意味着消费者也会停滞不前。如果没有生产者支持任务,则它们无事可做。

请注意,这原则上适用于任何类型的锁,而不仅是自旋锁-但自旋锁的破坏性效果更为突出,因为CPU会保持燃烧周期,而一无所获。

现在想象一下,除了上述内容之外,还有一些程序员有一个绝妙的主意,即使用将亲和力设置为第一个内核的专用线程,因此RDTSC将在所有处理器上提供可靠的结果(无论如何,它不会,但是有些人会这样认为)。


这就是为什么良好的自旋锁会在很短的时间内降级到其他锁类型,而如果过去必须降低同一锁的使用率,那么更好的自旋锁会更快地降级。
伊恩

-1

如果我理解您的要求,这是可能的,但这是一件非常非常糟糕的事情。

您所描述的规范示例将维护一个计数器,该计数器由多个线程递增。这几乎不需要计算能力,但需要线程之间的仔细协调。只要一次仅一个线程进行一次增量(实际上是一次读取,然后进行加法,再进行写入),则其值将始终是正确的。这是因为一个线程将始终读取正确的“上一个”值,加一个并写入正确的“下一个”值。使两个线程同时进入操作,这两个线程将读取相同的“上一个”值,从增量中获得相同的结果,并写入相同的“下一个”值。即使两个线程认为计数器各自都执行了一次,计数器实际上也只会有效地递增一次。

时间与正确性之间的这种依赖关系是计算机科学所称的竞争条件

通常通过使用同步机制来避免争用情况,以确保要对共享数据进行操作的线程必须排队才能访问。上述计数器可能为此使用读写锁

在没有访问《龙腾世纪:审判》的内部设计的情况下,任何人都只能猜测其行为方式。但是我会根据自己的经验看一些事情:

该程序可能基于已调整的四个线程,因此,只要线程在其自己的物理内核上运行时几乎不间断,则一切正常。“调整”可能以重新布置代码或在战略性位置插入睡眠的形式出现,以缓解在开发过程中因种族条件引起的错误。同样,这都是推测,但是我看到种族条件“解决”的方式比我想计算的次数要多。

在不适合其环境的任何功能上运行这种方式的程序,都会导致时序变化,这是由于代码运行速度不佳或上下文切换可能导致的。上下文切换以物理方式(即,CPU的物理核心在其逻辑核心所承担的工作之间)和逻辑方式(即,CPU上的OS将工作分配给核心)之间进行切换,但是两者之间存在很大的差异将是“预期的”执行时间。那会带来不良行为。

如果《龙腾世纪:审判》没有采取简单的步骤来确保在继续操作之前有足够的物理核心可用,那是EA的错。他们可能会花很少的钱来寻求来自试图在太少的硬件上运行游戏的人的支持电话和电子邮件。


1
一些玩家说,这是由于DRM运行在2个内核上,而实际游戏也运行在2个内核上。当DRM和游戏线程在同一内核上运行时,它会陷入混乱。但这对我来说听起来并不正确,可能是一个对sw或hw体系结构了解不多的玩家编写的一个小故事。
uylmz 2015年

4
竞争条件实际上与核心计数没有太大关系,-1 ...具有多个虚拟线程的单个核心计算机的竞争条件可能完全取决于运行时的时间分片技术,或者许多核心系统可以避免依赖于所有竞争条件关于门诊手术有多严格...
Jimmy Hoffa

1
@Reek:如果不了解程序的工作原理,那一切都是猜测。对我而言,仅执行DRM的两个核心似乎有点多余。
Blrfl 2015年

1
@JimmyHoffa:我不同意。即使没有引起不良行为,竞赛条件仍然是竞赛条件。核心数量可以影响是否发生这种行为,这是发问者问的,但是我没有将其作为唯一变量。
Blrfl 2015年

-1

Windows为此提供了内置功能:函数GetLogicalProcessorInformation在Windows API中。您可以从程序中调用它以获取有关内核,虚拟内核和超线程的信息。

因此,您的问题的答案将是:是的。


3
我不是在问“我能从代码中找出核心吗?” ...这样的代码是不正确的(迫使您购买更昂贵的CPU来运行程序-无需计算能力)。
uylmz

3
该功能提供了更多信息,而不仅仅是原始的“内核数”。借助此信息,您可以推断出物理核心,逻辑核心等。如果可以扣除,则可以编写软件以使用此信息。不管是好是坏(当您看到4个核心但少于4个物理核心时,将崩溃程序)。
Pieter B

1
这可能在Windows中有效,但是OSX / Linux / iOS / Android / etc等呢?虽然它是将游戏视为出现这种行为的实例(自然相关性是Windows =游戏),但它似乎并不是特定于游戏的请求。
罗伯特

对于《龙腾世纪》这样的游戏,所讨论的系统是Windows / XBox / PS4。

Linux具有/proc/cpuinfosysconf(_SC_NPROCESSORS_ONLN)(后者在POSIX中提到)。但是,使用信息来强制执行最低性能阈值仍然是非常糟糕的形式。
cHao 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.