How can I create and reassign threads based on user input?

43 Views Asked by At

So I am trying to improve my sudoku validator and test it's performance, I wanted to know that how I can reassign threads, I changed up the code a bit but when I am specifying the number of threads, it is only scanning that many items in the sudoku

Enter the size of Sudoku (4, 9, 16, etc.): 4
Enter the number of threads: 2
Thread 1 checks row 1 and is valid.
Thread 2 checks column 1 and is valid.
Sudoku is valid.
The total time taken is 278.00 microseconds.

Here is my code

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <math.h>

#define MAX_SIZE 64

int sudoku[MAX_SIZE][MAX_SIZE];

// Function to check if a number can be placed at a given position
int is_valid(int row, int col, int num, int size) {
    // Check row
    for (int i = 0; i < size; i++) {
        if (i != col && sudoku[row][i] == num) {
            return 0;
        }
    }

    // Check column
    for (int i = 0; i < size; i++) {
        if (i != row && sudoku[i][col] == num) {
            return 0;
        }
    }

    // Check subgrid
    int subgrid_size = (int)sqrt(size);
    int start_row = row - row % subgrid_size;
    int start_col = col - col % subgrid_size;
    for (int i = start_row; i < start_row + subgrid_size; i++) {
        for (int j = start_col; j < start_col + subgrid_size; j++) {
            if (i != row && j != col && sudoku[i][j] == num) {
                return 0;
            }
        }
    }

    return 1;
}

// Function to solve the Sudoku using backtracking
int solve_sudoku(int row, int col, int size) {
    if (row == size) {
        return 1;
    }
    if (col == size) {
        return solve_sudoku(row + 1, 0, size);
    }
    if (sudoku[row][col] != 0) {
        return solve_sudoku(row, col + 1, size);
    }

    for (int num = 1; num <= size; num++) {
        if (is_valid(row, col, num, size)) {
            sudoku[row][col] = num;
            if (solve_sudoku(row, col + 1, size)) {
                return 1;
            }
            sudoku[row][col] = 0;
        }
    }

    return 0;
}

// Struct to pass arguments to thread function
typedef struct {
    int thread_id;
    int start;
    int end;
    int size;
    int valid;
} ThreadArgs;

// Thread function to check validity of rows, columns, and subgrids
void *thread_function(void *args) {
    ThreadArgs *thread_args = (ThreadArgs *)args;

    int local_valid = 1;

    // Check rows
    if (thread_args->thread_id <= thread_args->size) {
        int row = thread_args->thread_id - 1;
        for (int j = 0; j < thread_args->size; j++) {
            if (!is_valid(row, j, sudoku[row][j], thread_args->size)) {
                local_valid = 0;
                break;
            }
        }
        // Print row validation message
        if (local_valid) {
            printf("Thread %d checks row %d and is valid.\n", thread_args->thread_id, thread_args->thread_id);
        } else {
            printf("Thread %d checks row %d and is invalid.\n", thread_args->thread_id, thread_args->thread_id);
        }
    }

    // Check columns
    if (thread_args->thread_id > thread_args->size && thread_args->thread_id <= 2 * thread_args->size) {
        int col = thread_args->thread_id - 1 - thread_args->size;
        for (int i = 0; i < thread_args->size; i++) {
            if (!is_valid(i, col, sudoku[i][col], thread_args->size)) {
                local_valid = 0;
                break;
            }
        }
        // Print column validation message
        if (local_valid) {
            printf("Thread %d checks column %d and is valid.\n", thread_args->thread_id, thread_args->thread_id - thread_args->size);
        } else {
            printf("Thread %d checks column %d and is invalid.\n", thread_args->thread_id, thread_args->thread_id - thread_args->size);
        }
    }

    // Check subgrids
    if (thread_args->thread_id > 2 * thread_args->size && thread_args->thread_id <= 3 * thread_args->size) {
        int subgrid_size = (int)sqrt(thread_args->size);
        int subgrid_num = thread_args->thread_id - 2 * thread_args->size;
        int start_row = ((subgrid_num - 1) / subgrid_size) * subgrid_size;
        int start_col = ((subgrid_num - 1) % subgrid_size) * subgrid_size;
        for (int i = start_row; i < start_row + subgrid_size; i++) {
            for (int j = start_col; j < start_col + subgrid_size; j++) {
                if (!is_valid(i, j, sudoku[i][j], thread_args->size)) {
                    local_valid = 0;
                    break;
                }
            }
        }
        // Print subgrid validation message
        if (local_valid) {
            printf("Thread %d checks subgrid %d and is valid.\n", thread_args->thread_id, subgrid_num);
        } else {
            printf("Thread %d checks subgrid %d and is invalid.\n", thread_args->thread_id, subgrid_num);
        }
    }

    // Update overall validity (only thread 1)
    if (thread_args->thread_id == 1) {
        thread_args->valid = local_valid;
    }

    pthread_exit(NULL);
}

int main() {
    int size, K;

    printf("Enter the size of Sudoku (4, 9, 16, etc.): ");
    scanf("%d", &size);

    if (size > MAX_SIZE || (int)sqrt(size) != sqrt(size)) {
        printf("Sudoku size must be a square number less than or equal to 64.\n");
        return 1;
    }

    printf("Enter the number of threads: ");
    scanf("%d", &K);

    if (K < 1) {
        printf("Number of threads must be at least 1.\n");
        return 1;
    }

    FILE *file = fopen("input.tex", "r");
    if (file == NULL) {
        printf("Error opening file.\n");
        return 1;
    }

    fscanf(file, "%d", &size);
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            fscanf(file, "%d", &sudoku[i][j]);
        }
    }
    fclose(file);
    clock_t start, end;
    double cpu_time_used;

    start = clock();


    int valid = 1;

    // Array to hold pthread IDs
    pthread_t threads[K];
    // Array to hold thread arguments
    ThreadArgs thread_args[K];

    // Create and execute threads
    for (int i = 0; i < K; i++) {
        thread_args[i].thread_id = i + 1;
        thread_args[i].start = i * size / K + 1;
        thread_args[i].end = (i + 1) * size / K;
        thread_args[i].size = size;
        thread_args[i].valid = 1;
        int rc = pthread_create(&threads[i], NULL, thread_function, (void *)&thread_args[i]);
        if (rc) {
            printf("Error: Unable to create thread %d.\n", i + 1);
            exit(-1);
        }
    }

    // Join threads
    for (int i = 0; i < K; i++) {
        pthread_join(threads[i], NULL);
        if (!thread_args[i].valid) {
            valid = 0;
        }
    }

    if (valid) {
        printf("Sudoku is valid.\n");
    } else {
        printf("Sudoku is invalid.\n");
    }
    
        end = clock();
    cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
    double microseconds = cpu_time_used * 1000000;

    printf("The total time taken is %.2f microseconds.\n", microseconds);

    return 0;


}

I want it to reassign the thread to scanning something else, like once thread 1 is done scanning row 1, it should get reassigned to row 2 or col 2, or smth.

0

There are 0 best solutions below