鱼C论坛

 找回密码
 立即注册
查看: 175|回复: 1

数据混乱问题

[复制链接]
发表于 2025-3-10 20:58:17 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
在测试batch_process_avx2函数中发现,数据发生混乱,测试案例落了两个黑子,所有的白子数据正常都应该为0才对,但是在函数中发生了混乱。
我想知道为什么会发生数据混乱的问题,大致方向,我好进行排查
在打印案例中第一轮在未处理签,白子所有数据均为0,正常。处理后第4,第五有异常,变成了一,期望值应该是0。在白棋内部打印并未触发,索引也已经打印

  1. this line 147 Running test_get_move function ...
  2. [DEBUG] GET_SORT_MOVES line 483 data number is :16 success !

  3. +++++ [debug] batch_process_avx2 line 252 simd_white[1,2,5]++++++:
  4. :572 :0 :0 :0 :0 :0
  5. :572 :0 :0 :0 :0 :0
  6. :572 :0 :0 :0 :0 :0
  7. :572 :0 :0 :0 :0 :0
  8. :572 :0 :0 :0 :0 :0
  9. :572 :0 :0 :0 :0 :0
  10. :572 :0 :0 :0 :0 :0
  11. :572 :0 :0 :0 :0 :0
  12. |-|-|-|-| [debug] batch_process_avx2 line 250 player= 1 and  BLACK_PLAYER= 1 <k:j> <1:0> | <1:1> | <1:2> | <1:3> | <1:4> | <1:5> | <1:6> | <1:7> |
  13. --- [debug] batch_process_avx2 line 252 simd_white[1,2,5]++++++:
  14. :572 :0 :0 :0 :1 :0
  15. :572 :0 :0 :0 :1 :0
  16. :572 :0 :0 :0 :1 :0
  17. :572 :0 :0 :0 :0 :0
  18. :572 :0 :0 :0 :0 :0
  19. :572 :0 :0 :0 :0 :0
  20. :572 :0 :0 :0 :0 :0
  21. :572 :0 :0 :0 :0 :1
  22. [DEBUG] batch 0 Rating: -632 -632 -632 368 368 368 368 -9632

  23. +++++ [debug] batch_process_avx2 line 252 simd_white[1,2,5]++++++:
  24. :572 :0 :0 :0 :0 :0
  25. :572 :0 :0 :0 :0 :0
  26. :572 :0 :0 :0 :0 :0
  27. :572 :0 :0 :0 :0 :0
  28. :572 :0 :0 :0 :0 :0
  29. :572 :0 :0 :0 :0 :0
  30. :572 :0 :0 :0 :0 :0
  31. :572 :0 :0 :0 :0 :0
  32. |-|-|-|-| [debug] batch_process_avx2 line 250 player= 1 and  BLACK_PLAYER= 1 <k:j> <2:0> | <5:1> | <5:2> | <1:3> | <1:4> | <5:5> | <5:6> | <2:7> |
  33. --- [debug] batch_process_avx2 line 252 simd_white[1,2,5]++++++:
  34. :572 :0 :0 :0 :0 :0
  35. :572 :0 :0 :0 :0 :0
  36. :572 :0 :0 :0 :0 :0
  37. :572 :0 :0 :0 :0 :0
  38. :572 :0 :0 :0 :0 :0
  39. :572 :0 :0 :0 :0 :0
  40. :572 :0 :0 :0 :0 :0
  41. :572 :0 :0 :0 :0 :0
  42. [DEBUG] batch 8 Rating: 377 10367 10367 368 368 10367 10367 377
  43. this line 147-174 Running function test_get_move... success Passed!
复制代码



GET_SORT_MOVES函数
  1.     CORE_API void GET_SORT_MOVES(AlignedSIMDContext* ctx, int player, int top_n) noexcept {
  2.         if (!ctx || ctx->undo_top >= 255) {
  3.             ctx->num_sorted_moves = 0;
  4.             return;
  5.         }

  6.         // 生成候选着法
  7.         std::vector<std::pair<int, int>> history;
  8.         history.reserve(ctx->undo_top);
  9.         for (int i = 0; i < ctx->undo_top; ++i) {
  10.             history.emplace_back(ctx->undo_stack[i].x, ctx->undo_stack[i].y);
  11.         }
  12.         auto candidates = generate_candidates(history);
  13.         ctx->num_sorted_moves = 0;
  14.         if (candidates.empty()) return;

  15.         std::vector<SIMDContext> thread_ctxs(omp_get_max_threads());
  16.         std::vector<int> scores(candidates.size());
  17.         std::vector<Move> temp_moves;
  18.         std::cout << "[DEBUG] GET_SORT_MOVES line 483 data number is :" << candidates.size() << " success ! \n ";


  19. #pragma omp parallel
  20.         {
  21.             const int tid = omp_get_thread_num();

  22. #pragma omp for schedule(static, 64)
  23.             for (int i = 0; i < candidates.size(); i += SIMD_BATCH_SIZE) {
  24.                 copy_core_data(&thread_ctxs[tid], ctx);
  25.                 const int batch = std::min(SIMD_BATCH_SIZE, int(candidates.size() - i));
  26.                 batch_process_avx2(
  27.                     &thread_ctxs[tid],
  28.                     {candidates.begin() + i, candidates.begin() + i + batch},
  29.                     player,
  30.                     scores.data() + i
  31.                 );
  32.                 std::cout << "\n[DEBUG] batch " << i << " Rating: ";
  33.                 for (int j = 0; j < batch; ++j) {
  34.                     std::cout << scores[i + j] << " ";
  35.                 }
  36.                 std::cout << std::endl << std::flush;
  37.             }
  38.         }


  39.         // 主线程处理排序
  40.         temp_moves.reserve(candidates.size());
  41.         for (size_t i = 0; i < candidates.size(); ++i) {
  42.             temp_moves.push_back({ scores[i], { candidates[i].first, candidates[i].second } });
  43.         }

  44.         const int partial_sort_size = std::min(static_cast<int>(temp_moves.size()), top_n * 2);
  45.         std::partial_sort(
  46.             temp_moves.begin(),
  47.             temp_moves.begin() + partial_sort_size,
  48.             temp_moves.end(),
  49.             [](const Move& a, const Move& b) { return a.score > b.score; }
  50.         );

  51.         ctx->num_sorted_moves = std::min(top_n, static_cast<int>(temp_moves.size()));
  52.         for (int i = 0; i < ctx->num_sorted_moves; ++i) {
  53.             if (i >= MAX_SORTED_MOVES) break;
  54.             ctx->sorted_moves[i] = temp_moves[i];
  55.         }
  56.     }

  57. }
复制代码


copy_core_data函数
  1.     inline void copy_core_data(
  2.         SIMDContext* dst,
  3.         const AlignedSIMDContext* src
  4.     ) {
  5.         static_assert(sizeof(dst->vec_states) == sizeof(src->vec_states),
  6.                      "VectorState 大小不匹配");
  7.         memcpy(dst->vec_states, src->vec_states, sizeof(VectorState)*MAX_VECTORS);

  8.         for (int k = 0; k < 6; ++k) {
  9.             for (int j = 0; j < SIMD_WIDTH; ++j) {
  10.                 dst->simd_black[k][j] = src->black_counts[k];
  11.                 dst->simd_white[k][j] = src->white_counts[k];
  12.             }
  13.         }
  14.     }
复制代码


batch_process_avx2函数
  1. void batch_process_avx2(
  2.     SIMDContext* ctx,
  3.     const std::vector<std::pair<int, int>>& moves,
  4.     int player,
  5.     int* scores)
  6. {

  7.     alignas(32) int indices[SIMD_WIDTH];

  8.     for (size_t i = 0; i < moves.size(); i += SIMD_WIDTH) {
  9.         printf("\n+++++ [debug] batch_process_avx2 line 252 simd_white[1,2,5]++++++: ");
  10.         for (int j = 0; j < 8; ++j) {
  11.             printf("\n");
  12.             for (int k = 0; k < 6; ++k) {
  13.                 printf(" :%d", ctx->simd_white[k][j]);
  14.             }

  15.         }
  16.         const int batch = std::min(SIMD_WIDTH, static_cast<int>(moves.size() - i));

  17.         // 填充索引数组
  18.         for (int j = 0; j < batch; ++j) {
  19.             const auto& [x, y] = moves[i + j];
  20.             indices[j] = y * BOARD_SIZE + x;
  21.         }
  22.         for (int j = batch; j < SIMD_WIDTH; ++j) {
  23.             indices[j] = 0;
  24.         }

  25.         __m256i v_idx = _mm256_load_si256(reinterpret_cast<__m256i*>(indices));

  26.         // 根据玩家更新计数器
  27.         __m256i v_counts;
  28.         alignas(32) int new_counts[SIMD_WIDTH];
  29.         alignas(32) int stored_indices[SIMD_WIDTH];
  30.         _mm256_store_si256(reinterpret_cast<__m256i*>(stored_indices), v_idx);

  31.         if (player == BLACK_PLAYER) {
  32.             v_counts = _mm256_i32gather_epi32(ctx->black_counts, v_idx, sizeof(int32_t));
  33.             v_counts = _mm256_add_epi32(v_counts, _mm256_set1_epi32(1));
  34.             _mm256_store_si256(reinterpret_cast<__m256i*>(new_counts), v_counts);
  35.             for (int j = 0; j < batch; ++j) {
  36.                 ctx->black_counts[stored_indices[j]] = new_counts[j];
  37.             }
  38.         } else {
  39.             v_counts = _mm256_i32gather_epi32(ctx->white_counts, v_idx, sizeof(int32_t));
  40.             v_counts = _mm256_add_epi32(v_counts, _mm256_set1_epi32(1));
  41.             _mm256_store_si256(reinterpret_cast<__m256i*>(new_counts), v_counts);
  42.             for (int j = 0; j < batch; ++j) {
  43.                 ctx->white_counts[stored_indices[j]] = new_counts[j];
  44.             }
  45.         }
  46.         // 更新SIMD计数器
  47.         printf("\n|-|-|-|-| [debug] batch_process_avx2 line 250 player= %d and  BLACK_PLAYER= %d <k:j> ",player,BLACK_PLAYER);
  48.         for (int m = 0; m < batch; ++m) {
  49.             const int k = std::clamp(new_counts[m], 0, 5);
  50.             printf("<%d:%d> | ",k ,m);
  51.             if (player == BLACK_PLAYER) {
  52.                 ctx->simd_black[k][m]++;
  53.             } else {
  54.                 printf("<> | <> | <> | <> | <> | <> | <> | <> | <> | <> | <> | <> | ");
  55.                 ctx->simd_white[k][m]++;
  56.             }
  57.         }

  58.         __m256i v_scores = calculate_scores_avx2(ctx, player);
  59.         printf("\n--- [debug] batch_process_avx2 line 252 simd_white[1,2,5]++++++: ");
  60.         for (int j = 0; j < 8; ++j) {
  61.             printf("\n");
  62.             for (int k = 0; k < 6; ++k) {
  63.                 printf(" :%d", ctx->simd_white[k][j]);
  64.             }

  65.         }
  66.         alignas(32) int score_values[SIMD_WIDTH];
  67.         _mm256_store_si256(reinterpret_cast<__m256i*>(score_values), v_scores);
  68.         for (int j = 0; j < batch; ++j) {
  69.             scores[i + j] = score_values[j];
  70.         }
  71.     }
  72. }
复制代码


两个数据体结构
  1. struct alignas(64) SIMDContext {
  2.     VectorState vec_states[MAX_VECTORS];
  3.     alignas(32) int32_t black_counts[6];
  4.     alignas(32) int32_t white_counts[6];
  5.     // 核心状态(32字节对齐)
  6.     alignas(32) int32_t simd_black[6][8];
  7.     alignas(32) int32_t simd_white[6][8];
  8. };


  9. class CORE_API alignas(SIMD_ALIGNMENT) AlignedSIMDContext {
  10. public:

  11.     Vector vectors[MAX_VECTORS];
  12.     VectorState vec_states[MAX_VECTORS];
  13.     Move sorted_moves[MAX_CELLS];
  14.     int32_t num_sorted_moves = 0;

  15.     alignas(32) int32_t black_counts[6];
  16.     alignas(32) int32_t white_counts[6];
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2025-3-10 20:58:29 | 显示全部楼层
数据混乱的可能原因有以下几个方向,你可以根据这些方向进行排查:  

1. 线程安全问题  
你的代码可能在多个线程中并行执行,而 `ctx->white_counts` 和 `ctx->black_counts` 可能没有正确同步,导致数据竞争。可以尝试使用 `#pragma omp critical` 或者 `std::atomic<int32_t>` 来确保数据一致性。  

2. SIMD 访问越界  
在 `batch_process_avx2` 函数中,你使用 `_mm256_i32gather_epi32` 进行数据加载,确保 `ctx->white_counts` 和 `ctx->black_counts` 的内存对齐,并且 `indices` 没有超出数组范围。  

3. 变量未正确初始化  
检查 `ctx->white_counts` 和 `ctx->black_counts` 是否在 `SIMDContext` 结构体初始化时被正确赋值,避免未定义行为。  

4. 误修改数据  
在 `batch_process_avx2` 里,你使用 `_mm256_store_si256` 存储 `new_counts`,但 `ctx->white_counts` 可能被错误地更新。可以在 `for` 循环中打印 `indices` 和 `new_counts`,确保它们的值正确。  

5. 结构体对齐问题  
`SIMDContext` 结构体使用 `alignas(32)` 进行对齐,但 `AlignedSIMDContext` 可能没有完全匹配,导致 `ctx->white_counts` 访问异常。可以尝试 `static_assert(alignof(SIMDContext) == 32, "Alignment issue")` 进行检查。  

你可以从这些方向入手,逐步排查问题。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-10 00:03

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表