我有一個分配一個問題:並行線程分配輸出誤差
我有一個數組座標A的在XYZ空間10000點,並與中心0.5,0.5,0.5起始立方體和每一側有1個長度。 立方體包含所有10k點 然後,立方體將分成8個相同的較小立方體,每個立方體將包含10k點的較小部分。
因此,主線程會產生8個線程,每個立方體一個,根據num_child(*參見下面的解釋)找到每個立方體的中心並計算它包含的點數。 在每個線程中,我創建一個臨時結構來執行計算,然後將結構推送到全局向量。 (*例如以0.5,0.5爲中心的二維框將分成4:a(0.25,0.25),b(0.75,0.25),c(0.75,0.25),b(0.75,0.75))。
當我運行該程序時,我得到的輸出是「10000 240 240 240 240 240 240 240 240」,這是錯誤的。如果我在gdb中運行該程序並逐步完成代碼,則結果是正確的。
任何可能出錯的地方?如果您需要在代碼的任何部分,更多的解釋,請告訴我...
謝謝您的時間
PS:您將需要-std = C++ 11個-pthread標誌進行編譯。我知道C++ 11具有內置線程,但分配的要點是在pthread中完成。
更新:我做了一些戳在代碼中,我發現所有的框都有相同的中心(0.75,0.75,0.75)。此外,我設定爲「0的情況下」在gdb斷點,但它從來沒有斷
#include <iostream>
#include <random>
#include <thread>
#include <vector>
#define N 10000
#define S 20
typedef struct Box{
int level, child[8], n;
float center[3];
}Box;
static double A[N][3]; //Coordinate array
std::vector<Box> box;
//initializing mutexes and a variable to hold the running threads
int running_threads;
pthread_mutex_t running_mutex = PTHREAD_MUTEX_INITIALIZER;
//arguments structer
struct arg_struct{;
int num_child,level;
};
void *create_child(void *arguments){
Box temp;
pthread_mutex_lock(&running_mutex);
arg_struct *args=(arg_struct*)arguments;
int num_child=args->num_child;
temp.level=args->level;
float akmi=1/pow(2,args->level);
pthread_mutex_unlock(&running_mutex);
float d=(0.5/pow(2,temp.level));
switch (num_child){
case 0:
temp.center[0]=0.5-d;
temp.center[1]=0.5-d;
temp.center[2]=0.5-d;
break;
case 1:
temp.center[0]=0.5+d;
temp.center[1]=0.5-d;
temp.center[2]=0.5-d;
break;
case 2:
temp.center[0]=0.5-d;
temp.center[1]=0.5+d;
temp.center[2]=0.5-d;
break;
case 3:
temp.center[0]=0.5+d;
temp.center[1]=0.5+d;
temp.center[2]=0.5-d;
break;
case 4:
temp.center[0]=0.5-d;
temp.center[1]=0.5-d;
temp.center[2]=0.5+d;
break;
case 5:
temp.center[0]=0.5+d;
temp.center[1]=0.5-d;
temp.center[2]=0.5+d;
break;
case 6:
temp.center[0]=0.5-d;
temp.center[1]=0.5+d;
temp.center[2]=0.5+d;
break;
case 7:
temp.center[0]=0.5+d;
temp.center[1]=0.5+d;
temp.center[2]=0.5+d;
break;
}
int number=0;
for(int i=0;i<N;i++){
if ((A[i][0]>=(temp.center[0]-akmi/2)) && (A[i][0]<=(temp.center[0]+akmi/2))){
if((A[i][1]>=temp.center[1]-akmi/2)&&(A[i][1]<=temp.center[1]+akmi/2)){
if((A[i][2]>=temp.center[2]-akmi/2)&&(A[i][2]<=temp.center[2]+akmi/2)){
number++;
}
}
}
}
pthread_mutex_lock(&running_mutex);
temp.n=number;
box.push_back(temp);
running_threads--;
pthread_mutex_unlock(&running_mutex);
}
int main(){
//Generate random A array
const double pi = 3.14159265358979323846;
std::default_random_engine rnd;
std::uniform_real_distribution<double> dist(0.0, 1.0);
for(int i=0; i<N; i++)
{
double z = dist(rnd);
double t = (pi/2.0)*dist(rnd);
double r = sqrt(1.0-z*z);
A[i][0]=r*cos(t);
A[i][1]=r*sin(t);
A[i][2]=z;
}
std::cout<<"\nCoordinates array completed\n";
///////
Box temp;
arg_struct *args=new arg_struct;
pthread_t threads[8];
//Original Box
temp.level=0;
temp.n=N;
temp.center[0]=0.5;
temp.center[1]=0.5;
temp.center[2]=0.5;
box.push_back(temp);
//Starting threads
for (int i=0;i<8;i++){
pthread_mutex_lock(&running_mutex);
args->level=1;
args->num_child=i;
running_threads++;
pthread_mutex_unlock(&running_mutex);
pthread_create(&threads[i],NULL,create_child,(void*)args);
}
while(running_threads>0){
}
for (int i=0;i<9;i++){
std::cout<<box[i].n<<"\n";
}
return 0;}