多线程正在减慢 OpenGl 循环
Multithreading is slowing down OpenGl loop
我目前正在使用 C++ 中的 OpenGL 编写类似地图生成器的 minecraft。我有 AMD Rayzen 5 3600 6 核。
因此,当我尝试在我的主循环中添加多线程来调用我的块生成时,它会减慢渲染速度。 我没有使用多线程进行渲染。
我正在 Windows 使用 MinGw 编译代码,多线程工作在 posix。
问题是我不明白为什么它使我的渲染变慢。即使我尝试创建 ONLY ONE 线程,我也会失去 FPS。即使我创建了一个线程来完成简单的任务,比如 :
std::cout << "Thread #" << i << "\n";
这会降低渲染速度。
我的编译标志是-pthread -lopengl32 -lglu32 -lgdi32 -luser32 -lkernel32 -lglfw3dll -O3
我要补充的是,我在学校使用的是 MacOS,多线程不会减慢渲染速度。我假设是 MinGW 问题。
如果你有任何想法可以帮助我,我会采纳。感谢您的回复!
这是我的循环:
while (!glfwWindowShouldClose(window))
{
Frustum frustum;
//fps(window);
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
processInput(window);
glClearColor(0.69f, 0.94f, 0.95f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.use();
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 1000.0f);
shader.setMat4("projection", projection);
glm::mat4 view = camera.GetViewMatrix();
shader.setMat4("view", view);
frustum.Transform(projection, view);
shader.setVec3("lightPos", glm::vec3(0.7, 0.2, 0.5));
shader.setVec3("viewPos", camera.Position);
displayChunk(shader, vox, &chunks, frustum);
glDepthFunc(GL_LEQUAL); // change depth function so depth test passes when values are equal to depth buffer's content
skyboxShader.use();
view = glm::mat4(glm::mat3(camera.GetViewMatrix())); // remove translation from the view matrix
skyboxShader.setMat4("view", view);
skyboxShader.setMat4("projection", projection);
// skybox cube
glBindVertexArray(skybox.skyboxVAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, skybox.cubemapTexture);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glDepthFunc(GL_LESS); // set depth function back to default
glfwSwapBuffers(window);
glfwPollEvents();
for (unsigned i = 0; i < 1; ++i)
{
threads[i] = std::thread([&mtx, i]
{
{
// Use a lexical scope and lock_guard to safely lock the mutex only for
// the duration of std::cout usage.
std::lock_guard<std::mutex> iolock(mtx);
std::cout << "Thread #" << i << " is running\n";
}
});
}
for (auto &t : threads)
{
t.join();
}
}
线程和进程在Linux下基本是一回事,都是在内部调用clone()创建的。所以你可以看到创建一个线程并不便宜,而且你在每个循环中都做了几次!
不要为此自责,第一代 Web 服务器 (Apache) 也是如此,它们为每个连接生成一个进程或线程。随着时间的推移,他们意识到仅创建 process/thread 是花费大部分时间的地方。创建进程或线程可能需要几毫秒。
下一个发展是线程池,我建议您这样做。您应该做的是预先创建所有线程并使用互斥锁和条件变量锁定它们。当你有工作要做时,你将数据推入他们的队列或对象并触发条件变量,这将解锁互斥锁并释放线程。这通常只会花费您 3-10 微秒,这比您现在拥有的要好一千倍。
你可以自己写线程池as in this tutorial or ou can use a predefined pool as the one provided by boost::thread_pool。
如果您甚至觉得 3-10 微秒太多了,您可以让线程以 100% 的速度旋转 cpu 并使用像 boost spsc container 这样的无锁容器进行通信。在这种情况下,线程之间的延迟下降到几十纳秒。这种方法的缺点是您的线程将始终消耗 100% 的内核,即使什么都不做也是如此。
我目前正在使用 C++ 中的 OpenGL 编写类似地图生成器的 minecraft。我有 AMD Rayzen 5 3600 6 核。
因此,当我尝试在我的主循环中添加多线程来调用我的块生成时,它会减慢渲染速度。 我没有使用多线程进行渲染。
我正在 Windows 使用 MinGw 编译代码,多线程工作在 posix。
问题是我不明白为什么它使我的渲染变慢。即使我尝试创建 ONLY ONE 线程,我也会失去 FPS。即使我创建了一个线程来完成简单的任务,比如 :
std::cout << "Thread #" << i << "\n";
这会降低渲染速度。
我的编译标志是-pthread -lopengl32 -lglu32 -lgdi32 -luser32 -lkernel32 -lglfw3dll -O3
我要补充的是,我在学校使用的是 MacOS,多线程不会减慢渲染速度。我假设是 MinGW 问题。
如果你有任何想法可以帮助我,我会采纳。感谢您的回复!
这是我的循环:
while (!glfwWindowShouldClose(window))
{
Frustum frustum;
//fps(window);
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
processInput(window);
glClearColor(0.69f, 0.94f, 0.95f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shader.use();
glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 1000.0f);
shader.setMat4("projection", projection);
glm::mat4 view = camera.GetViewMatrix();
shader.setMat4("view", view);
frustum.Transform(projection, view);
shader.setVec3("lightPos", glm::vec3(0.7, 0.2, 0.5));
shader.setVec3("viewPos", camera.Position);
displayChunk(shader, vox, &chunks, frustum);
glDepthFunc(GL_LEQUAL); // change depth function so depth test passes when values are equal to depth buffer's content
skyboxShader.use();
view = glm::mat4(glm::mat3(camera.GetViewMatrix())); // remove translation from the view matrix
skyboxShader.setMat4("view", view);
skyboxShader.setMat4("projection", projection);
// skybox cube
glBindVertexArray(skybox.skyboxVAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, skybox.cubemapTexture);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glDepthFunc(GL_LESS); // set depth function back to default
glfwSwapBuffers(window);
glfwPollEvents();
for (unsigned i = 0; i < 1; ++i)
{
threads[i] = std::thread([&mtx, i]
{
{
// Use a lexical scope and lock_guard to safely lock the mutex only for
// the duration of std::cout usage.
std::lock_guard<std::mutex> iolock(mtx);
std::cout << "Thread #" << i << " is running\n";
}
});
}
for (auto &t : threads)
{
t.join();
}
}
线程和进程在Linux下基本是一回事,都是在内部调用clone()创建的。所以你可以看到创建一个线程并不便宜,而且你在每个循环中都做了几次!
不要为此自责,第一代 Web 服务器 (Apache) 也是如此,它们为每个连接生成一个进程或线程。随着时间的推移,他们意识到仅创建 process/thread 是花费大部分时间的地方。创建进程或线程可能需要几毫秒。
下一个发展是线程池,我建议您这样做。您应该做的是预先创建所有线程并使用互斥锁和条件变量锁定它们。当你有工作要做时,你将数据推入他们的队列或对象并触发条件变量,这将解锁互斥锁并释放线程。这通常只会花费您 3-10 微秒,这比您现在拥有的要好一千倍。
你可以自己写线程池as in this tutorial or ou can use a predefined pool as the one provided by boost::thread_pool。
如果您甚至觉得 3-10 微秒太多了,您可以让线程以 100% 的速度旋转 cpu 并使用像 boost spsc container 这样的无锁容器进行通信。在这种情况下,线程之间的延迟下降到几十纳秒。这种方法的缺点是您的线程将始终消耗 100% 的内核,即使什么都不做也是如此。