一旦使用 pthread 满足条件,for 循环就不会终止
For loop not terminating once condition is met using pthread
当我发现for 循环没有终止时,我正在编写一段多线程代码。起始代码大概是这样的:
for(int i = V-1-tid; i >= 0; i-=NTHREADS){
*/ stuff */
}
V 和 NTHREADS 是常量,tid 是使用 pthread_create
.
传递的线程 ID
然后我从循环中删除了所有内容并编写了类似这样的内容以确保没有任何干扰 i
:
for(int i = 0; i<100; i++){
std::cout<<i<<"<100? "<<(i<100)<<std::endl;
}
这还不止。
我使用简单的方式生成线程:
for(int i = 0; i < NTHREADS; i++){
pthread_create(&(threads[i]), NULL, foo, &(parameters[i]));
}
我尝试将 i
声明为 volatile
,但这没有任何改变。
如果我用 -O0
编译,那么循环会正确停止,但是 -O0
以上的所有内容都有同样的问题。
我正在使用 gcc 9.4.0
,更具体地说是 g++-9 (Homebrew GCC 9.4.0) 9.4.0
,我正在使用的标志是:
-O3 -mavx -mavx2 -mfma -std=c++11 -march=native -fno-rtti -lquadmath -lpthread -g
我目前正在查看 gcc 的程序集输出以查看发生了什么,但理解优化的 x86 有点痛苦。
我是不是遗漏了什么明显的东西?有什么我可以尝试的吗?
编辑:添加示例。
示例代码:
#include <iostream>
#include <pthread.h>
#define NTHREADS 1
void *foo(void *args){
for(int i = 0; i < 100; i++){
std::cout<<i<<std::endl;
}
}
int main(){
pthread_t threads[NTHREADS];
for(int i = 0; i < NTHREADS; i++){
pthread_create(&(threads[i]), NULL, foo, NULL);
}
for(int i = 0; i < NTHREADS; i++){
pthread_join(threads[i], NULL);
}
}
我得到的输出可以在这里看到:godbolt.org/z/Mfjrj6Khr
代码有未定义的行为 - 一个函数有 return 类型 void *
但没有 return 任何东西。编译器感到困惑并生成无限循环。
确保启用并收听编译器警告,它们会告诉您:
1.cpp: In function ‘void* foo(void*)’:
1.cpp:7:1: warning: no return statement in function returning non-void [-Wreturn-type]
7 | }
| ^
我能想到的最短的 MCVE 说明了这一点:
#include <cstdio>
void* foo() {
for(int i = 0; i < 100; i++){
putchar(i);
}
}
int main() {
foo();
}
当使用 -O3
在 g++11.1 的 Godbolt 上编译时:
foo():
push rbx
xor ebx, ebx
.L2:
mov rsi, QWORD PTR stdout[rip]
mov edi, ebx
add ebx, 1
call putc
jmp .L2 # Just an endless loop.
main:
sub rsp, 8
call foo()
当我发现for 循环没有终止时,我正在编写一段多线程代码。起始代码大概是这样的:
for(int i = V-1-tid; i >= 0; i-=NTHREADS){
*/ stuff */
}
V 和 NTHREADS 是常量,tid 是使用 pthread_create
.
然后我从循环中删除了所有内容并编写了类似这样的内容以确保没有任何干扰 i
:
for(int i = 0; i<100; i++){
std::cout<<i<<"<100? "<<(i<100)<<std::endl;
}
这还不止。
我使用简单的方式生成线程:
for(int i = 0; i < NTHREADS; i++){
pthread_create(&(threads[i]), NULL, foo, &(parameters[i]));
}
我尝试将 i
声明为 volatile
,但这没有任何改变。
如果我用 -O0
编译,那么循环会正确停止,但是 -O0
以上的所有内容都有同样的问题。
我正在使用 gcc 9.4.0
,更具体地说是 g++-9 (Homebrew GCC 9.4.0) 9.4.0
,我正在使用的标志是:
-O3 -mavx -mavx2 -mfma -std=c++11 -march=native -fno-rtti -lquadmath -lpthread -g
我目前正在查看 gcc 的程序集输出以查看发生了什么,但理解优化的 x86 有点痛苦。
我是不是遗漏了什么明显的东西?有什么我可以尝试的吗?
编辑:添加示例。
示例代码:
#include <iostream>
#include <pthread.h>
#define NTHREADS 1
void *foo(void *args){
for(int i = 0; i < 100; i++){
std::cout<<i<<std::endl;
}
}
int main(){
pthread_t threads[NTHREADS];
for(int i = 0; i < NTHREADS; i++){
pthread_create(&(threads[i]), NULL, foo, NULL);
}
for(int i = 0; i < NTHREADS; i++){
pthread_join(threads[i], NULL);
}
}
我得到的输出可以在这里看到:godbolt.org/z/Mfjrj6Khr
代码有未定义的行为 - 一个函数有 return 类型 void *
但没有 return 任何东西。编译器感到困惑并生成无限循环。
确保启用并收听编译器警告,它们会告诉您:
1.cpp: In function ‘void* foo(void*)’:
1.cpp:7:1: warning: no return statement in function returning non-void [-Wreturn-type]
7 | }
| ^
我能想到的最短的 MCVE 说明了这一点:
#include <cstdio>
void* foo() {
for(int i = 0; i < 100; i++){
putchar(i);
}
}
int main() {
foo();
}
当使用 -O3
在 g++11.1 的 Godbolt 上编译时:
foo():
push rbx
xor ebx, ebx
.L2:
mov rsi, QWORD PTR stdout[rip]
mov edi, ebx
add ebx, 1
call putc
jmp .L2 # Just an endless loop.
main:
sub rsp, 8
call foo()