voidinit() { // ---------------------------------------------------------- // if the total amount of computation is too small, // use a single thread to avoid wasting time and resources if (MIN(M, N) < 1000) { blockLength = MIN(M, N), T = 1; } else { blockLength = 1000; } roundOfN = N / blockLength, roundOfM = M / blockLength; #ifdef CHECK_MODEL printf("round of N: %d round of M: %d\n", roundOfN, roundOfM); printf("blockLength:%d, T:%d\n", blockLength, T); #endif // ----------------------------------------------------------
// ---------------------------------------------------------- // calculate how many blocks there are in total on each slash int min_MN = MIN(roundOfN, roundOfM), max_MN = MAX(roundOfN, roundOfM); for (int i = 1; i <= roundOfN + roundOfM - 1; i++) { if (i <= max_MN && i >= min_MN) { nums[i] = min_MN; } else { nums[i] = MIN(i, roundOfN + roundOfM - i); } } #ifdef CHECK_MODEL printf("------------nums array--------------\n"); for (int i = 1; i <= roundOfN + roundOfM - 1; i++) { printf("%d ", nums[i]); } printf("\n"); printf("------------nums array--------------\n"); #endif // ----------------------------------------------------------- }
voidLCS() { // create threads for (int i = 0; i < T; i++) { create(Tworker); }
cur = 0, total = roundOfN + roundOfM - 1;
// total scheduler while (cur < total) { mutex_lock(&round_lk); cur++; count = nums[cur] / T + (nums[cur] % T != 0); cond_broadcast(&start); mutex_unlock(&round_lk);
#ifdef CHECK_MODEL printf("-------------------------\n"); printf(" cur thread: %d number of this threads: %d\n", cur, nums[cur]); printf("-------------------------\n"); #endif
// wait for all threads to finish calculating this slash mutex_lock(&done_lk); while (doneNum < T) { cond_wait(&done, &done_lk); } doneNum = 0; mutex_unlock(&done_lk); }
// ----------------------------------------------------------- // complete the calculation of the excess content for (int i = blockLength * roundOfN; i < N; i++) { for (int j = 0; j < M; j++) { int skip_a = DP(i - 1, j); int skip_b = DP(i, j - 1); int take_both = DP(i - 1, j - 1) + (A[i] == B[j]); dp[i][j] = MAX3(skip_a, skip_b, take_both); } } for (int i = 0; i < N; i++) { for (int j = blockLength * roundOfM; j < M; j++) { int skip_a = DP(i - 1, j); int skip_b = DP(i, j - 1); int take_both = DP(i - 1, j - 1) + (A[i] == B[j]); dp[i][j] = MAX3(skip_a, skip_b, take_both); } } // ----------------------------------------------------------- }
voidTworker(int id) { int thread_round = 1; while (1) { mutex_lock(&round_lk); while (thread_round != cur) { cond_wait(&start, &round_lk); } mutex_unlock(&round_lk);
// ----------------------------------------------------------- // calculate the start and end addresses of each block int shiftOfN = (MIN(thread_round, roundOfN) - 1) * blockLength; int shiftOfM = (MAX(0, thread_round - roundOfN)) * blockLength; int size = (id - 1) * count * blockLength; int startOfI = shiftOfN - size, startOfJ = shiftOfM + size; // -----------------------------------------------------------
// ----------------------------------------------------------- // complete the calculations that this thread needs to complete in this round for (int r = 1; r <= count; r++) { #ifdef CHECK_MODEL printf("id:%d round:%d cround:%d start of I: %d, start of J: %d\n", id, thread_round, r, startOfI, startOfJ); #endif // stop calculation when bounds are crossed if (OVERSTEP) { #ifdef CHECK_MODEL printf("|| id %d cround%d stackOverflow break\n", id, r); #endif break; }
// perform calculations on a block for (int i = startOfI; i < startOfI + blockLength; i++) { for (int j = startOfJ; j < startOfJ + blockLength; j++) { int skip_a = DP(i - 1, j); int skip_b = DP(i, j - 1); int take_both = DP(i - 1, j - 1) + (A[i] == B[j]); dp[i][j] = MAX3(skip_a, skip_b, take_both); } }