Lazy SMP troubles

Discussion of anything and everything relating to chess playing software and machines.

Moderator: Ras

adityachandra
Posts: 23
Joined: Sun Apr 23, 2023 9:26 am
Full name: Aditya Chandra

Lazy SMP troubles

Post by adityachandra »

I have been trying to implement Lazy SMP multithreading for the past week, however my results have been underwhelming as at most I only get a 2x speedup when on 8 threads compared to 1 thread. I did all the usual such as keeping a seperate history and killer table for each thread, and increasing the depth by one for every odd thread, to create divergence early on so each thread is not just repeating the same work. But still to no avail. As reference I just attached my iterative deepening method, which implements the multithreading. Perhaps you guys could find mistakes?

Code: Select all

void searchPosition(board& inputBoard) {
  std::vector<int> moves;
  generateMoves(inputBoard, moves, false);
  board workerDatas[numberOfThreads];
  for (int i = 0; i < numberOfThreads; i++) workerDatas[i] = inputBoard;
  board& firstWorkerData = workerDatas[0];
  negamax(firstWorkerData, 1, -20000, 20000, moves, true);
  int threadsToSpawn = numberOfThreads - 1;
  int currentDepth = 2;
  while (true) {
    std::thread workerThreads[threadsToSpawn];
    for (int i = 0; i < threadsToSpawn; i++) {
      board& inputWorkerData = workerDatas[i + 1];
      workerThreads[i] = std::thread(negamax, std::ref(inputWorkerData), currentDepth + (i & 1), -20000, 20000, std::ref(moves), true);
    }
    int score = negamax(firstWorkerData, currentDepth, -20000, 20000, moves, true);
    for (int i = 0; i < threadsToSpawn; i++) {
      // Stop all the threads once main thread has finished.
      workerDatas[i + 1].isSearchStopped = true;
      if (workerThreads[i].joinable()) workerThreads[i].join();
    }
    // Set the threads as unstopped once they actually have stopped so that we can search again.
    for (int i = 0; i < threadsToSpawn; i++) workerDatas[i + 1].isSearchStopped = false;
    if (firstWorkerData.isSearchStopped) break;
    std::chrono::steady_clock::time_point currentTime = std::chrono::steady_clock::now();
    int timeElapsed = (int)std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - startTime).count();
    double ordering = 100.0 * ((double)firstWorkerData.failedHighFirst / (double)firstWorkerData.failedHigh);
    std::cout << "Depth: " << currentDepth << " Time: " << timeElapsed << " Nodes: " << firstWorkerData.nodes << " Ordering: " << ordering << "%" << " Score: " << score << " Principal Variation: ";
    principalVariation.clear();
    std::vector<std::string> internalPrincipleVariationAlgebraic;
    retrievePrincipleVariation(inputBoard, principalVariation, internalPrincipleVariationAlgebraic);
    for (int i = 0; i < internalPrincipleVariationAlgebraic.size(); i++) std::cout << internalPrincipleVariationAlgebraic[i] << " ";
    std::cout << std::endl;
    currentDepth++;
  }
}