【问题标题】:C++ threads in recursion not working properly递归中的 C++ 线程无法正常工作
【发布时间】:2020-10-21 06:35:12
【问题描述】:

我目前正在使用 MINIMAX 算法构建一个国际象棋 AI。最初没有线程很好,但它最多只有 5 层,所以为了增加深度,我使用了多线程,但它陷入了无限循环,有人可以帮忙让它工作吗?

代码:

void* best_move(void *_args){

    struct forThread *args = (struct forThread *) _args;

    for(int i=0; i<8; ++i){
        for(int j=0; j<8; ++j){
            args->res += args->state_score[i][j];
            printf("%c", state[i][j]);
        }
        printf("\n");
    }
    if(args->depth == 5){
        //printf("Return value in the last node = %lld\n", current_score);
        pthread_exit((void*)(args->res));
    }

    // TURN OF THE PLAYER THAT MAXIMIZES THE SCORE :
    int mid[] = {0, 7, 1, 6, 2, 5, 3, 4};
    if(args->depth % 2 == 0){
        //printf("Reached the maximizing player\n");
        int ans = -1e8;
        for(int i=0; i<8; ++i){
            for(int j=0; j<8; ++j){
                if(isUpper(args->state[i][mid[j]]) && args->state_score[i][mid[j]]>0){
                    vector<pair<int, int>> possible_moves = get_moves(i, mid[j], args->state);
                    if(possible_moves.size() == 0) continue;
                    for(auto u : possible_moves){
                        int x = u.first, y = u.second;
                        int removed_points = args->state_score[x][y];
                        char state_copy[8][9];
                        int state_score_copy[8][8];
                        for(int k=0; k<8; ++k){
                            for(int io=0; io<9; ++io){
                                if(io!=8) state_score_copy[k][io] = args->state_score[k][io];
                                state_copy[k][io] = args->state[k][io];
                            }
                        }
                        int new_score = args->res - args->state_score[x][y];
                        if(args->depth >= 3 && new_score == args->start_score) continue;

                        state_copy[x][y] = state_copy[i][mid[j]];
                        state_copy[i][mid[j]] = '_';
                        state_score_copy[x][y] = state_score_copy[i][mid[j]];
                        state_score_copy[i][mid[j]] = 0;

                        struct forThread *arg = (forThread*) malloc (sizeof (struct forThread));
                        arg->depth = args->depth + 1;
                        arg->depth = args->start_score;
                        for(int k=0; k<8; ++k){
                            for(int io=0; io<9; ++io){
                                if(io!=8) arg->state_score[k][io] = args->state_score[k][io];
                                arg->state[k][io] = args->state[k][io];
                            }
                        }
                        arg->alpha = args->alpha;
                        arg->beta = args->beta;
                        arg->res = -1;

                        pthread_t id;
                        pthread_create(&id, NULL, best_move, arg);
                        void *result = NULL;

                        //long long res = best_move(depth+1, state_copy, state_score_copy, alpha, beta);

                        pthread_join(id, &result);
                        ans = min(ans, (int)result);
                        args->res = ans;


                        //long long res = best_move(depth+1, state_copy, state_score_copy, alpha, beta);
                        //printf("%lld\n", res);
                        args->alpha = max(args->alpha, ans);
                        if(args->beta <= args->alpha) break;
                        if(args->depth == 0 && ans == args->res){
                            //printf("got the answer = %d\n", ans);
                            moveX = i;
                            moveY = mid[j];
                            toX = x;
                            toY = y;
                        }
                    }
                }
            }
        }
        pthread_exit((void*)(args->res));
    }


    else{

        int ans = +1e8;
        //printf("Reached the minimizing player\n");
        for(int i=0; i<8; ++i){
            for(int j=0; j<8; ++j){
                if(isLower(args->state[i][mid[j]]) && args->state_score[i][mid[j]]<0){
                    vector<pair<int, int>> possible_moves = get_moves(i, mid[j], args->state);
                    if(possible_moves.size() == 0) continue;
                    for(auto u : possible_moves){
                        int x = u.first, y = u.second;
                        int removed_points = args->state_score[x][y];
                        char state_copy[8][9];
                        int state_score_copy[8][8];
                        for(int k=0; k<8; ++k){
                            for(int io=0; io<9; ++io){
                                if(io!=9) state_score_copy[k][io] = args->state_score[k][io];
                                state_copy[k][io] = args->state[k][io];
                            }
                        }
                        int new_score = args->res - args->state_score[x][y];
                        if(args->depth >= 3 && new_score == args->start_score) continue;

                        state_copy[x][y] = state_copy[i][mid[j]];
                        state_copy[i][mid[j]] = '_';
                        state_score_copy[x][y] = state_score_copy[i][mid[j]];
                        state_score_copy[i][mid[j]] = 0;

                        struct forThread *arg = (forThread*) malloc (sizeof (struct forThread));
                        arg->depth = args->depth + 1;
                        arg->depth = args->start_score;
                        for(int k=0; k<8; ++k){
                            for(int io=0; io<9; ++io){
                                if(io!=8) arg->state_score[k][io] = args->state_score[k][io];
                                arg->state[k][io] = args->state[k][io];
                            }
                        }
                        arg->alpha = args->alpha;
                        arg->beta = args->beta;
                        arg->res = -1;

                        pthread_t id;
                        pthread_create(&id, NULL, best_move, arg);
                        void *result = NULL;
                        //long long res = best_move(depth+1, state_copy, state_score_copy, alpha, beta);

                        pthread_join(id, &result);
                        ans = min(ans, (int)result);
                        args->res = ans;

                        args->beta = min(ans, args->beta);
                        if(args->beta <= args->alpha) break;
                    }
                }
            }
        }
        pthread_exit((void*)(args->res));
    }

}

【问题讨论】:

  • pthread_create(&amp;id, ...)直接后跟pthread_join(id, ...)有什么用?这与仅以非线程方式调用线程函数没有什么不同。
  • 我需要在这里有点挑剔,抱歉。那是 pthreads,没有 c++ 线程。这里似乎没有一行 C++ 代码。 std::thread 将是您在 C++ 中使用的东西
  • 这是我第一次使用线程,我找到了很多方法,但其中很少有人告诉如何获取返回值,你能建议一些简单的方法来从函数中获取返回值吗?
  • @Reinhold 有一个向量,所以不被 C 编译器编译就足够了。我希望 C++ 不是通过先教 C 来教的。
  • @StevenAnderson 你可能想看看std::async en.cppreference.com/w/cpp/thread/async 你也可能更喜欢这个:auto arg = new forThread() 而不是struct forThread *arg = (forThread*) malloc (sizeof (struct forThread));

标签: c++ multithreading artificial-intelligence chess minimax


【解决方案1】:

这可能是罪魁祸首:

arg->depth = args->depth + 1;
arg->depth = args->start_score;

您想在代码的第二行将depth 更改为start_score 两次。

您还必须 free() 分配的 args 或使用更 C++ 风格的内存管理,因为您的程序现在有内存泄漏。

【讨论】:

  • @StevenAnderson 您是否已经确认这是问题所在还是还有其他问题?
  • 还有一些其他问题,所以我尝试使用 std::async 函数,但仍然出现错误。链接:stackoverflow.com/questions/64465888/…
猜你喜欢
  • 2016-06-16
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
  • 2015-11-11
  • 1970-01-01
  • 2019-06-07
  • 1970-01-01
相关资源
最近更新 更多