How to parallelize knight tour problem with Pthreads? - c

I am trying to paralelize knight tour problem with pthreads but I am getting some errors. I am very new at c language. I guess the code has pointer related problem. can you give me some clue about how to solve it?
I am trying to apply paralel recursive approach. First i was supposed to create 8 threads, then based on moves, new threads are created. perDepth is the limit of creating new threads. i am planing to rewrite this code with multple number of "perDepth"s and compare performance based on perDepth.
\#define HAVE_STRUCT_TIMESPEC
\#include \<pthread.h\>
\#include \<stdio.h\>
\#include \<time.h\>
\#define N 5
int perDepth = 1;
pthread_t thread\[N\];
int count = 0;
int is_valid(int i, int j, int sol\[N + 1\]\[N + 1\])
{
if (i \>= 1 && i \<= N && j \>= 1 && j \<= N && sol\[i\]\[j\] == -1)
return 1;
return 0;
}
int knight_tour(int sol\[N + 1\]\[N + 1\], int i, int j, int step_count, int x_move\[\], int y_move\[\])
{
if (step_count == N \* N)
{
count++;
return 1;
}
int k;
for (k = 0; k \< 8; k++)
{
int next_i = i + x_move\[k\];
int next_j = j + y_move\[k\];
if (is_valid(i + x_move[k], j + y_move[k], sol))
{
sol[next_i][next_j] = step_count;
if (step_count <= perDepth)
{
pthread_create(&thread[k], NULL, knight_tour, NULL);
}
else
{
knight_tour(sol, next_i, next_j, step_count + 1, x_move, y_move);
sol[i + x_move[k]][j + y_move[k]] = -1; // backtracking
}
}
}
return 0;
}
int start_knight_tour()
{
int sol[N + 1][N + 1];
int i, j;
for (i = 1; i <= N; i++)
{
for (j = 1; j <= N; j++)
{
sol[i][j] = -1;
}
}
int x_move[] = {2, 1, -1, -2, -2, -1, 1, 2};
int y_move[] = {1, 2, 2, 1, -1, -2, -2, -1};
sol[1][1] = 0; // placing knight at cell(1, 1)
if (knight_tour(sol, 1, 1, 1, x_move, y_move))
{
for (i = 1; i <= N; i++)
{
for (j = 1; j <= N; j++)
{
printf("%d\t", sol[i][j]);
}
printf("\n");
}
return 1;
}
return 0;
}
int main()
{
clock_t t;
t = clock();
pthread_create(&thread\[N\], NULL, start_knight_tour, NULL);
pthread_join(thread\[N\], NULL);
t = clock() - t;
double time_taken = ((double)t) / CLOCKS_PER_SEC; // in seconds
printf("start_knight_tour() took %f seconds to execute \\n", time_taken);
printf("%d\\n", count);
return 0;
}
error message
main.c: In function ‘knight_tour’:
main.c:38:50: warning: passing argument 3 of ‘pthread_create’ from incompatible pointer type \[-Wincompatible-pointer-types\]
38 | pthread_create(&thread\[k\], NULL, knight_tour, NULL);
| ^\~\~\~\~\~\~\~\~\~\~
| |
| int (*)(int (*)\[6\], int, int, int, int *, int )
In file included from main.c:2:
/usr/include/pthread.h:204:36: note: expected ‘void \* (*)(void *)’ but argument is of type ‘int (*)(int ()\[6\], int, int, int, int \*, int *)’
204 | void (*\__start_routine) (void *),
| \~\~\~\~\~\~\~\~^\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~
main.c: In function ‘main’:
main.c:90:38: warning: passing argument 3 of ‘pthread_create’ from incompatible pointer type \[-Wincompatible-pointer-types\]
90 | pthread_create(&thread\[N\], NULL, start_knight_tour, NULL);
| ^\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~
| |
| int (*)()
In file included from main.c:2:
/usr/include/pthread.h:204:36: note: expected ‘void \* ()(void *)’ but argument is of type ‘int (*)()’
204 | void *(*\__start_routine) (void \*),
| \~\~\~\~\~\~\~\~^\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~

Related

Matrix creation / value setting / value copying in C using functions and return values

I have a task of creating a matrix, that is the size of NxN, where N is a given parameter.
The matrix should be filled with random 0s and 1s.
I have tried the following code:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include <sys/wait.h>
#include <pthread.h>
int** createMatr(int N){
int** matr[10][10];
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
int rnd = rand() % 2;
matr[i][j] = rnd;
}
}
return matr;
}
void setValMatr(int N, int** matr[][10], int** newMatr[][10]){
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
newMatr[i][j] = matr[i][j];
}
}
}
void printMatr(int N, int** matr[][10]){
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
printf("%d ",matr[i][j]);
}
printf("\n");
}
}
int main(int argc, char* argv[]){
if(argc!=2){
perror("parameter error\n");
}
int N = atoi(argv[1]);
int** matrix[10][10];
int** helper[10][10];
setValMatr(N,createMatr(N), matrix);
setValMatr(N,matrix,helper);
printMatr(N, matrix);
return 0;
}
The compilation warnings this gives me are:
┌──(kali㉿kali)-[~/Desktop/Cprog/Linux2_Lab2]
└─$ gcc gvim2135_L2_1.c -o p
gvim2135_L2_1.c: In function ‘createMatr’:
gvim2135_L2_1.c:15:24: warning: assignment to ‘int **’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
15 | matr[i][j] = rnd;
| ^
gvim2135_L2_1.c:18:12: warning: returning ‘int ** (*)[10]’ from a function with incompatible return type ‘int **’ [-Wincompatible-pointer-types]
18 | return matr;
| ^~~~
gvim2135_L2_1.c:18:12: warning: function returns address of local variable [-Wreturn-local-addr]
gvim2135_L2_1.c: In function ‘main’:
gvim2135_L2_1.c:47:18: warning: passing argument 2 of ‘setValMatr’ from incompatible pointer type [-Wincompatible-pointer-types]
47 | setValMatr(N,createMatr(N), matrix);
| ^~~~~~~~~~~~~
| |
| int **
gvim2135_L2_1.c:21:30: note: expected ‘int ** (*)[10]’ but argument is of type ‘int **’
21 | void setValMatr(int N, int** matr[][10], int** newMatr[][10]){
| ~~~~~~^~~~~~~~~~
After running I get the error:
Segmentation fault
With the int** matrix[][] notation you are not create a matrix but a matrix of matrix pointer. You can see a matrix as a pointer to an array of array: int** matrix.
So, your code become:
int** create_matrix(int size) {
int i, j, **matrix = (int **)malloc(size * sizeof(int*));
for (i = 0; i < size; ++i) {
matrix[i] = (int *)malloc(size * sizeof(int));
for (j = 0; j < size; ++j) {
matrix[i][j] = rand() % 2;
}
}
return matrix;
}
void print_matrix(int** matrix, int size) {
int i, j;
for (i = 0; i < size; ++i) {
for (j = 0; j < size; ++j) {
printf("%d | ", matrix[i][j]);
}
printf("\n");
}
}
Use a structure to describe matrices in general, for example
typedef struct imatrix imatrix;
struct imatrix {
int rows;
int cols;
int *data;
};
static inline int imatrix_get(const imatrix *im, int row, int col, int outside)
{
if (!im || row < 0 || col < 0 || row >= im->rows || col >= im->cols)
return outside;
else
return im->data[row * (size_t)(im->cols) + col];
}
static inline void imatrix_set(imatrix *im, int row, int col, int value)
{
if (im && row >= 0 && col >= 0 && row < im->rows && col < im->cols)
im->data[row * (size_t)(im->cols) + col] = value;
}
void imatrix_free(imatrix *im)
{
if (im) {
free(im->data);
im->rows = 0;
im->cols = 0;
im->data = NULL;
}
}
int imatrix_new(imatrix *im, int rows, int cols)
{
if (!im)
return -1; /* No matrix specified */
im->rows = 0;
im->cols = 0;
im->data = NULL;
if (rows < 1 || cols < 1)
return -2; /* Invalid size */
const size_t rowsize = (size_t)cols * sizeof im->data[0];
const size_t datasize = (size_t)rows * rowsize;
if ((size_t)(datasize / rows) != rowsize ||
(size_t)(rowsize / cols) != sizeof im->data[0])
return -3; /* Matrix is too large */
im->data = malloc(datasize);
if (!im->data)
return -4; /* Not enough memory available */
im->rows = rows;
im->cols = cols;
return 0;
}
The idea is that imatrix is a structure that contains the number of rows and columns in the matrix, and a pointer to the (array of) data elements. If m is a properly initialized imatrix, element at row r, column c is m->data[r*(size_t)(m->cols) + c].
Note that the int type is not large enough on many architectures to for the index, so we need to cast the number of columns to the proper type, size_t (which is the proper type for all in-memory sizes and offsets).
If you have e.g. imatrix m;, you need to initialize it (and dynamically allocate memory for it, say 30 rows and 20 columns) by calling imatrix_new(&m, 30, 20);. It will return 0 if successful, and negative error code if it fails.
The imatrix_get() and imatrix_set() functions are convenient accessor functions, that will not try to access the matrix contents outside of bounds. You do not need to use them in your own functions, if you make sure your loops etc. are always within range; you can then safely use the im->data[r * (size_t)(im->cols) + c] idiom.
When you no longer need the matrix, you discard it with a simple imatrix_free(&m) call.

Pointer to Array in function call in c

i'm a bit confused about using pointers.
I want to hand over the array to the pointer and then get the result of the function from the pointer.
The function just returns the minimum of an array.
int *minimum(int (*A)[5]){
int min = 0;
int A_result[1];
for (int i = 0; i < 5; i++) {
if ((*A)[i]< (*A)[min])
min = i;
}
A_result[0] = (*A)[min];
return A_result; //line 39
}
int main(void) {
int A[5] = {5, 7, 3, 6, 4};
int (*array_ptr)[5] = minimum(&A); //line 45
printf("%d ", *array_ptr);
return EXIT_SUCCESS;
}
by now i get the following errors:
line 45: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
initialization from incompatible pointer type [-Wincompatible-pointer-types]
line 39:
function returns address of local variable [-Wreturn-local-addr]
There is no need to pass pointer to array to the function second_lowest. Also, no point in returning a pointer from the function second_lowest. I modified your code :
int second_lowest(int *A) {
int min = 0;
int A_result;
for (int i = 0; i < 5; i++) {
if (A[i] < A[min])
min = i;
}
A_result = A[min];
return A_result; //line 39
}
int main(void) {
int A[5] = { 5, 7, 3, 6, 4 };
int res = second_lowest(A); //line 45
printf("%d ", res);
return EXIT_SUCCESS;
}
Hope it helps.

fwrite incorrect value assignment writing matrixes in a binary file

I am trying to make a program that writes matrixes in a binary file. The 1st two items are the rows and columns of the matrix, and then the rest of the values.
The data of matrix are floats (when it was all in ints, it worked, but when I changed the values to floats it stopped working).
The next piece of code is the method to write the matrix in a binary file. It is the part where everything crashes.
The Matrix definition is the next one:
#include <stdio.h>
#include <stdlib.h>
typedef struct Matriz_t {
int numFilas;
int numColumnas;
float** datos;
}Matriz_t;
//create matrix
Matriz_t* crearMatriz(int numFilas, int numColumnas)
{
Matriz_t* nMatriz = NULL;
int i = 0;
nMatriz = (Matriz_t*)malloc(sizeof(Matriz_t));
nMatriz->numColumnas = numColumnas;
nMatriz->numFilas = numFilas;
nMatriz->datos = (float**)malloc(sizeof(float*)*numFilas);
for (i = 0; i < numColumnas; i++) {
nMatriz->datos[i] = (float*)malloc(sizeof(float)*numColumnas);
}
return nMatriz;
}
//read matrix
void leerMatriz(char * nomFichero, Matriz_t ** m1, int traspuesta)
{
FILE* f1 = NULL;
int i, j;
int numFilas = 0, numColumnas = 0;
f1 = fopen(nomFichero, "r");
fread(&(numFilas), sizeof(int), 1, f1); .
fread(&(numColumnas), sizeof(int), 1, f1);
(*m1) = crearMatriz(numFilas, numColumnas);
if (traspuesta) {
for (i = 0; i < (*m1)->numFilas; i++)
for (j = 0; j<(*m1)->numColumnas; j++)
fread(&((*m1)->datos[j][i]), sizeof(float), 1, f1);
}
else {
for (i = 0; i < (*m1)->numFilas; i++)
fread((*m1)->datos[i], sizeof(float), (*m1)->numColumnas, f1);
}
fclose(f1);
}
//write matrix
void escribirMatriz(char * nomFichero, Matriz_t * m1, int traspuesta)
{
FILE* f1 = NULL;
int i, j;
f1 = fopen(nomFichero, "w");
fwrite(&(m1->numFilas), sizeof(int), 1, f1);
fwrite(&(m1->numColumnas), sizeof(int), 1, f1);
if (traspuesta) {
for (i = 0; i < m1->numFilas; i++)
for (j = 0; j < m1->numColumnas; j++)
fwrite(&(m1->datos[j][i]), sizeof(float), 1, f1);
}
else {
for (i = 0; i < m1->numFilas; i++)
fwrite(m1->datos[i], sizeof(float), m1->numColumnas, f1);
}
fclose(f1);
}
//main
int main()
{
int i = 0, j = 0;
Matriz_t *m1, *m2, *mres;
m1 = crearMatriz(4, 4);
m2 = crearMatriz(4, 4);
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++) {
m1->datos[i][j] = j;
m2->datos[i][j] = i;
}
printf("\n Matriz 1: \n");
printf("%d y %d ", m1->numFilas, m1->numColumnas);
for (i = 0; i < 4; i++) {
printf("\n");
for (j = 0; j < 4; j++) {
printf("%f ", m1->datos[i][j]);
}
}
printf("\n Matriz 2: \n");
for (i = 0; i < 4; i++) {
printf("\n");
for (j = 0; j < 4; j++) {
printf("%f ", m2->datos[i][j]);
}
}
escribirMatriz("matriz3.bin", &m1, 1);
escribirMatriz("matriz4.bin", &m2, 1);
//leer matriz
leerMatriz("matriz3.bin", &m1, 0);
leerMatriz("matriz4.bin", &m2, 0);
Changing the last number "traspuesta" (turn cols and rows) to all 1 1 may work but as the number of cols and rows are not correct, it cannot multiply (And that method is correct, but anyways, it should be alright to have 0's in everything).
Then I do a simple if to check if I can multiply those matrixes (M1 nxm and M2 ixj, can be multiplied if m==i, but as the writing method is not working, it never multiplies.
escribirMatriz("matriz3.bin", &m1, 1);
This is incorrect and any compiler made in this millennium should have at lest warned you about it.
mtrx.c:102:39: warning: passing argument 2 of ‘escribirMatriz’ from incompatible pointer type [-Wincompatible-pointer-types]
escribirMatriz("matriz3.bin", &m1, 1);
^
mtrx.c:53:6: note: expected ‘Matriz_t * {aka struct Matriz_t *}’ but argument is of type ‘Matriz_t ** {aka struct Matriz_t **}’
void escribirMatriz(char * nomFichero, Matriz_t * m1, int traspuesta)
^~~~~~~~~~~~~~
mtrx.c:103:39: warning: passing argument 2 of ‘escribirMatriz’ from incompatible pointer type [-Wincompatible-pointer-types]
escribirMatriz("matriz4.bin", &m2, 1);
^
mtrx.c:53:6: note: expected ‘Matriz_t * {aka struct Matriz_t *}’ but argument is of type ‘Matriz_t ** {aka struct Matriz_t **}’
void escribirMatriz(char * nomFichero, Matriz_t * m1, int traspuesta)
^~~~~~~~~~~~~~

Addition of a matrix using thread in c

The question is to add two matrix using thread,where a loop takes row element of 2 matrix and that thread creates thread to add the individual elements. Below is the code --
#include<stdio.h>
#include<pthread.h>
#include<error.h>
#include<stdlib.h>
#define r 2
#define c 3
struct mat{
int (*a)[r][c];
int (*b)[r][c];
int (*d)[r][c];
int m, n;
};
struct element{
int *a;
int *b;
int *d;
};
void* add_element(void* pelement){
struct element* e1 = pelement;
(*e1).d = (*e1).a + (*e1).b;
pthread_exit(NULL);
}
void* add_row(void* pmat){
struct mat *mat1 = pmat;
int i = 0, m = mat1->m, n = mat1->n;
for(i = 0; i < n; ++i){
pthread_t add_e;
struct element e1;
e1.a = (*mat1->a)[m][i];
e1.b = (*mat1->b)[m][i];
e1.d = (*mat1->d)[m][i];
if(pthread_create(&add_e, NULL, add_element, &e1) != 0){
perror("Unable to create thread\n");
exit(0);
}
(*mat1->d)[m][i] = e1.d;
pthread_join(add_e, NULL);
//(*(*mat1).d)[m][i] = (*(*mat1).a)[m][i] + (*(*mat1).b)[m][i];
}
pthread_exit(0);
}
int main()
{
int a[r][c] = {1, 2, 3, 4, 5, 6};
int b[r][c] = {1, 2, 3, 4, 5, 6};
int d[r][c] = {0, 0, 0, 0, 0, 0};
pthread_t add_mat[r];
struct mat mat1;
mat1.a = &a;
mat1.b = &b;
mat1.d = &d;
int i = 0;
for(i = 0; i < r; ++i){
mat1.m = i;
mat1.n = c;
if(pthread_create(&add_mat[i], NULL, add_row, &mat1) != 0){
perror("Unable to create thread\n");
exit(1);
}
pthread_join(add_mat[i], NULL);
}
for(i = 0; i < r; ++i){
int j = 0;
for(j = 0; j < c; ++j)
printf("%d ", d[i][j]);
printf("\n");
}
pthread_exit(NULL);
}
While executing, I am doing something wrong with the pointer. The error is like --
add_matrix.c: In function ‘add_element’:
add_matrix.c:20:20: error: invalid operands to binary + (have ‘int *’ and ‘int *’)
(*e1).d = (*e1).a + (*e1).b;
How can I handle the pointer in order to get the result?
Edit
I have solved it. Please ignore it.

Using a structure in a recursive function (referenced structure)

I'm having problems understanding how to write code that solves the following problem: I have a structure containing a 2D-array. Then I have a recursive function that take a pointer to the structure as an argument and I want the recursive function to be able to manipulate the structure sent, not a local copy.
The struct is initialized in the function initStruct, where memory for the 2D-array is allocated. The recursive function builds up an array and at a specific point calls a function to insert it into the structure's array.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int** spBasis(int);
void mpBasis(int**, int, int, int, int, int, int, int*, struct mpBasis *, int, int);
void initMpBasis(struct mpBasis *, int, int);
void insertMpState(struct mpBasis *, int *);
struct mpBasis {
int** basis;
int size;
int capacity;
};
int main() {
int a, b, c, d;
char maxE[256];
char noParticles[256];
char P[256];
char M[256];
FILE *fp;
int **spStates;
struct mpBasis *mp;
int mpState[6] = {0, 0, 0, 0, 0, 0};
printf("Input max e for sp states, no of particles, parity (1 for odd and 0 for even) and magnetic projection: ");
gets(maxE);
gets(noParticles);
gets(P);
gets(M);
spStates = spBasis(atoi(maxE));
fp = fopen("spStates.txt", "a+");
fprintf(fp, "E\tj\tl\tm\n");
for (a = 0; a < 330; a++) {
fprintf(fp, "State %d: ", a+1);
for (b = 0; b < 4; b++) {
fprintf(fp, "%d\t", spStates[a][b]);
}
fprintf(fp, "\n");
}
mp = malloc(sizeof(struct mpBasis));
initMpBasis(mp, 5449, 6);
for (c = 0; c < 5449; c++) {
for (d = 0; d < 6; d++) {
fprintf(fp, "%d: %d\t", c, mp->basis[c][d]);
}
fprintf(fp, "\n");
}
printf("%p\n", (void*) mp);
printf("hello 3");
mpBasis(spStates, 0, atoi(maxE), 0, atoi(M), 0, atoi(P), mpState, mp, 0, 0);
fclose(fp);
return 0;
}
int** spBasis(int maxE) {
int c;
int i, j, k, l;
int q = 0;
int** spStates;
spStates = (int**)malloc(330 * sizeof(int *));
for (c = 0; c < 330; c++) {
spStates[c] = malloc(4 * sizeof(int));
}
for (i = 0; i <= maxE; i++) {
for (j = i % 2; j <= i; j += 2) {
for (k = -(2 * j + 1); k <= (2 * j + 1); k += 2) {
spStates[q][0] = i;
spStates[q][1] = j;
spStates[q][2] = 2 * j + 1;
spStates[q][3] = k;
q += 1;
}
for (l = -(2 * j - 1); l <= (2 * j - 1); l += 2) {
spStates[q][0] = i;
spStates[q][1] = j;
spStates[q][2] = 2 * j - 1;
spStates[q][3] = l;
q += 1;
}
}
}
return spStates;
}
void mpBasis(int** spStates, int e, int maxE, int m, int M, int l,
int P, int * mpState, struct mpBasis *mpB, int position, int lastSpState) {
int i;
for (i = lastSpState; i < 330; i++) {
if (e > maxE) {
break;
} else if (position == 5) {
if (m == M && l % 2 == P) {
insertMpState(mpB, mpState);
break;
}
} else {
// add spState to mpState and make the recursive call for the next position
mpState[position] = i;
mpBasis(spStates, e + spStates[i][0], maxE, m + spStates[i][3], M,
l + spStates[i][1], P, mpState, mpB, position+1, i);
}
}
}
void initMpBasis(struct mpBasis *a, int initialSize, int sizeY) {
int c;
a->basis = (int **)malloc(initialSize * sizeof(int*));
for (c = 0; c < initialSize; c++) {
a->basis[c] = (int *) malloc(sizeY * sizeof(int));
}
a->size = 0;
a->capacity = initialSize;
}
void insertMpState(struct mpBasis *a, int* mpState) {
/*if (a->size == a->capacity) {
a->size *= 2;
a->basis = (int **)realloc(a->basis, a->size * sizeof(int));
}*/
a->basis[a->size++] = mpState;
}
Added all the code.
The problem is that after the recursive function has been called, the "basis" array in structure mpBasis still only contains random values, i.e. the mpBasis function hasn't done anything with it. Am I passing the mp argument by value here?
Thanks for your help!
The first step is to compile with warnings enabled. Eg if you are using GCC you can use option -Wall -Wextra.
EDIT:
(previous listing of >20 errors removed)
Ok, since you are using Visual Studio, enable warnings like this:
Open the project's Property Pages dialog box.
Select C/C++.
On the General property page, modify the Warning Level to /W4

Resources