简体   繁体   English

主线程和其他线程之间有什么区别?

[英]Any difference between main thread and other threads?

On GLFW FAQ , item 2.9 it is stated: 关于GLFW常见问题 ,项目2.9说明:

[...] It is strongly recommended that all OpenGL and GLFW calls (except for thread management and synchronization calls) are made from the main thread , which should not be a big problem since only a single window is supported. [...] 强烈建议所有OpenGL和GLFW调用 (线程管理和同步调用除外) 都是从主线程进行的 ,这不应该是一个大问题,因为只支持一个窗口。 This method is also compatible with the future direction of GLFW. 该方法也与GLFW的未来发展方向兼容。

The emphasis is mine. 重点是我的。

So, what is the difference between the main thread and other threads? 那么,主线程与其他线程有什么区别?

The question refers to an old GLFW API and FAQ, please see the updated GLFW FAQ , and GLFW thread safety documentation . 问题涉及旧的GLFW API和FAQ,请参阅更新的GLFW FAQGLFW线程安全文档

Some constraints remain, and many GLFW calls must be made from the main thread. 仍然存在一些约束,并且必须从主线程进行许多GLFW调用。 The difference between the main thread and other threads depends on platform specific behaviour for window creation, events etc which GLFW handles. 主线程和其他线程之间的区别取决于GLFW处理的窗口创建,事件等的平台特定行为。 For more detail please see this post on the official GLFW forum . 有关详细信息,请参阅官方GLFW论坛上的这篇文章

Once an OpenGL window has been created, the context can be made current on another thread and OpenGL calls can be made from that thread. 一旦创建了OpenGL窗口,就可以在另一个线程上使上下文成为当前状态,并且可以从该线程进行OpenGL调用。

The statement 该声明

"Is … thread safe? No. However, neither is OpenGL." “是......线程安全吗?不。但是,OpenGL也不是。”

is wrong. 是错的。 OpenGL is of course thread safe. OpenGL当然是线程安全的。

Here's the deal: For each thread either one or no OpenGL context can be bound to a drawable (made current). 这是交易:对于每个线程,一个或没有OpenGL上下文可以绑定到drawable(当前的)。 OpenGL calls operate on the context that is active in the thread the calls are made from. OpenGL调用对在调用的线程中处于活动状态的上下文进行操作。 It is perfectly possible to transfer a OpenGL context between threads. 完全可以在线程之间传输OpenGL上下文。 For this the context to be transfered first must be unbound, then it can be rebound in another thread. 为此,首先要转移的上下文必须是未绑定的,然后它可以在另一个线程中反弹。

Each OpenGL context manages its own set of state variable and objects (textures, buffers). 每个OpenGL上下文管理自己的一组状态变量和对象(纹理,缓冲区)。 However context can be "entangled", ie share their object space. 然而,上下文可以“纠缠”,即共享其对象空间。 State is still individual though. 国家仍然是个人。

A single drawable (window, PBuffer) can have multiple contexts from different threads being bound to. 单个drawable(窗口,PBuffer)可以具有来自绑定到的不同线程的多个上下文。 If contexts from different threads draw to the same drawable a race condition occours and the results are undefined. 如果来自不同线程的上下文绘制到相同的drawable,则会出现竞争条件并且结果未定义。 However in the case of depth tested drawing the outcome should be reasonable. 然而,在深度测试绘图的情况下,结果应该是合理的。 However simultanous drawing to a single drawable will strongly impair performance, so it better is avoided. 然而,同时绘制单个drawable会严重影响性能,因此最好避免使用。

The main use for multiple OpenGL contexts in multiple threads is to share their objects so that one thread can load and update data for the other context. 多线程中多个OpenGL上下文的主要用途是共享其对象,以便一个线程可以加载和更新其他上下文的数据。 It makes sense to bind the helper contexts to off-screen or hidden drawables to prevent race conditions to happen. 将帮助器上下文绑定到屏幕外或隐藏的drawable是有意义的,以防止发生竞争条件。

There's no technical difference between the threads. 线程之间没有技术差异。 From a programming point of view each thread will have a slightly different semantic, which is imposed by the programm running, not by the system architecture. 从编程的角度来看,每个线程将具有稍微不同的语义,这是由运行的程序强加的,而不是由系统架构强加的。 In the case of most OpenGL applications the conventional semantics are, that the main thread will create the window, draw all elements visible to the user (including OpenGL operations) and collect user input. 在大多数OpenGL应用程序的情况下,传统的语义是,主线程将创建窗口,绘制用户可见的所有元素(包括OpenGL操作)并收集用户输入。 The threads launched from the main thread are worker threads without direct user interaction. 从主线程启动的线程是工作线程,没有直接的用户交互。 However this task distribution is purely by choice and because it turned out to work well. 然而,这个任务分配纯粹是选择,因为它结果很好。 But it's perfectly possible, and sometimes advisable, to use a different scheme. 但是使用不同的方案是完全可能的,有时是可取的。 And like already said, there is no technical difference about the threads within a program. 就像已经说过的那样,程序中的线程没有技术差异。 All threads are equal rights citizens within a process. 所有线程都是进程中的平等权利公民。

The documentation is maybe worded in a slightly misleading way. 文档的措辞可能略有误导。 A better wording would be: 更好的措辞是:

It is strongly recommended that all OpenGL and GLFW calls (except for thread management and synchronization calls) are made from a single thread, preferrably the same one that called glfwInit and glfwOpenWindow , which should not be a big problem since only a single window is supported. 强烈建议所有OpenGL和GLFW调用(线程管理和同步调用除外)都来自单个线程,最好是调用glfwInitglfwOpenWindow的相同 ,这不应该是一个大问题,因为只支持一个窗口。 This method is also compatible with the future direction of GLFW. 该方法也与GLFW的未来发展方向兼容。

The reason for that is that OpenGL has the concept of a "current thread" for its contexts, which is the one thread that may legitimate modify or use that context at a given time. 原因是OpenGL具有针对其上下文的“当前线程”的概念,这是可以在给定时间合法修改或使用该上下文的一个线程。 A context initially belongs to the thread that created it. 上下文最初属于创建它的线程。 You can make it "current" in some other thread by calling wglMakeCurrent or glxMakeCurrent , which unlike GLFW is not portable (but GLFW might have a wrapper for that, I'm not sure). 您可以通过调用wglMakeCurrentglxMakeCurrent使其在某个其他线程中成为“当前”,这与GLFW不同,它不可移植(但GLFW可能有一个包装器,我不确定)。

It is of course very well possible to have several independent contexts, and it is possible to access the same context from several threads by making the same context current in each thread prior to using it. 当然很可能有几个独立的上下文,并且可以通过在使用它之前在每个线程中使相同的上下文变为当前来从多个线程访问相同的上下文。 And lastly, it is possible to have several contexts in several threads that share state. 最后,可以在多个共享状态的线程中有多个上下文。
However, none of these options is the regular case, as it either involves non-neglegible synchronization overhead or is not suitable for the common usage of OpenGL. 但是,这些选项都不是常规情况,因为它涉及不可忽略的同步开销或不适合OpenGL的常见用法。 Any other thing than "one thread, one context" usually, with very few exceptions, doesn't offer any advantage, but comes with needless complexity. 除了“一个线程,一个上下文”以外,除了极少数例外情况之外的任何其他事情都没有提供任何优势,但却带来了不必要的复杂性。

The regular case is therefore to have exactly one context that is used by exactly one thread, and optionally some worker threeads that help with shuffling data into mapped buffers. 因此, 常规情况是恰好有一个上下文仅由一个线程使用,并且可选地有一些工作者三个有助于将数据混洗到映射缓冲区中。

As for "main thread" versus "any thread", there is no difference. 至于“主线”与“任何线程”,没有区别。 The main thread is just incidentially the one that initializes GLFW (and thus OpenGL), most of the time. 主线程只是incidentially初始化GLFW(因此OpenGL的),大部分时间的一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM