#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <mpi.h>
enum {
ROWS = 1000,
COLUMNS = 1000
};
int isPalindrome(const char *str, int len) {
for (int i = 0; i < len / 2; i++) {
if (str[i] != str[len - i - 1]) {
return 0;
}
}
return 1;
}
int countPaL(const char **matrix, int row, int col, int len) {
int count = 0;
// Horizontal WISE
if (col + len <= COLUMNS) {
if (isPalindrome(matrix[row] + col, len)) {
count++;
}
}
// Vertical WISE
if (row + len <= ROWS) {
char *tmp
= (char *)malloc(len
* sizeof(char)); for (int i = 0; i < len; i++) {
tmp[i] = matrix[row + i][col];
}
if (isPalindrome(tmp, len)) {
count++;
}
}
// Diagonal WISE
if (row + len <= ROWS && col + len <= COLUMNS) {
char *tmp
= (char *)malloc(len
* sizeof(char)); for (int i = 0; i < len; i++) {
tmp[i] = matrix[row + i][col + i];
}
if (isPalindrome(tmp, len)) {
count++;
}
}
return count;
}
void broadCast(char** matrix) {
int i3 = 0;
while (i3 < ROWS) {
MPI_Bcast(matrix[i3], COLUMNS, MPI_CHAR, 0, MPI_COMM_WORLD);
i3++;
}
}
void Free(char** matrix){
int i5 = 0;
while (i5 < ROWS) {
i5++;
}
}
char** alloNgenMatrix(int rank){
char **matrix
= (char **)malloc(ROWS
* sizeof(char *)); int i1 = 0;
while (i1 < ROWS) {
matrix
[i1
] = (char*) malloc(COLUMNS
* sizeof(char)); i1++;
}
if (rank == 0) {
int i2 = 0;
while (i2 < ROWS) {
int j1 = 0;
while (j1 < COLUMNS) {
matrix
[i2
][j1
] = (rand() % 26) + 'A'; j1++;
}
i2++;
}
}
return matrix;
}
void findPalindrome(int rank, char** matrix, int length, int size){
double start_time = MPI_Wtime();
int local_count = 0, global_count = 0, i4 = rank;
while (i4 < ROWS) {
for (int j = 0; j < COLUMNS; j++) {
local_count += countPaL((const char **)matrix, i4, j, length);
}
i4 += size;
}
MPI_Reduce(&local_count, &global_count, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
double end_time = MPI_Wtime();
if (rank == 0) {
printf("%d palindromes of size %d found in %lf s. using %d processes.\n", global_count, length, end_time - start_time, size);
}
}
int main(int argc, char *argv[]) {
int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
// Allocate and generate matrix
char** matrix = alloNgenMatrix(rank);
// Broadcast matrix to all processes
broadCast(matrix);
MPI_Barrier(MPI_COMM_WORLD);
for (int length = 3; length < 7; ++ length) {
findPalindrome(rank, matrix, length, size);
}
if (rank == 0) {
printf("=============================***********=============================\n"); }
Free(matrix);
MPI_Finalize();
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8dGltZS5oPgojaW5jbHVkZSA8bXBpLmg+CgplbnVtIHsgCiAgICBST1dTID0gMTAwMCwKICAgIENPTFVNTlMgPSAxMDAwCn07CgppbnQgaXNQYWxpbmRyb21lKGNvbnN0IGNoYXIgKnN0ciwgaW50IGxlbikgewogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBsZW4gLyAyOyBpKyspIHsKICAgICAgICBpZiAoc3RyW2ldICE9IHN0cltsZW4gLSBpIC0gMV0pIHsKICAgICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIDE7Cn0KCmludCBjb3VudFBhTChjb25zdCBjaGFyICoqbWF0cml4LCBpbnQgcm93LCBpbnQgY29sLCBpbnQgbGVuKSB7CiAgICBpbnQgY291bnQgPSAwOwogICAgLy8gSG9yaXpvbnRhbCBXSVNFCiAgICBpZiAoY29sICsgbGVuIDw9IENPTFVNTlMpIHsKICAgICAgICBpZiAoaXNQYWxpbmRyb21lKG1hdHJpeFtyb3ddICsgY29sLCBsZW4pKSB7CiAgICAgICAgICAgIGNvdW50Kys7CiAgICAgICAgfQogICAgfQogICAgLy8gVmVydGljYWwgV0lTRQogICAgaWYgKHJvdyArIGxlbiA8PSBST1dTKSB7CiAgICAgICAgY2hhciAqdG1wID0gKGNoYXIgKiltYWxsb2MobGVuICogc2l6ZW9mKGNoYXIpKTsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7CiAgICAgICAgICAgIHRtcFtpXSA9IG1hdHJpeFtyb3cgKyBpXVtjb2xdOwogICAgICAgIH0KICAgICAgICBpZiAoaXNQYWxpbmRyb21lKHRtcCwgbGVuKSkgewogICAgICAgICAgICBjb3VudCsrOwogICAgICAgIH0KICAgICAgICBmcmVlKHRtcCk7CiAgICB9CiAgICAvLyBEaWFnb25hbCBXSVNFCiAgICBpZiAocm93ICsgbGVuIDw9IFJPV1MgJiYgY29sICsgbGVuIDw9IENPTFVNTlMpIHsKICAgICAgICBjaGFyICp0bXAgPSAoY2hhciAqKW1hbGxvYyhsZW4gKiBzaXplb2YoY2hhcikpOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbGVuOyBpKyspIHsKICAgICAgICAgICAgdG1wW2ldID0gbWF0cml4W3JvdyArIGldW2NvbCArIGldOwogICAgICAgIH0KICAgICAgICBpZiAoaXNQYWxpbmRyb21lKHRtcCwgbGVuKSkgewogICAgICAgICAgICBjb3VudCsrOwogICAgICAgIH0KICAgICAgICBmcmVlKHRtcCk7CiAgICB9CiAgICByZXR1cm4gY291bnQ7Cn0KCnZvaWQgYnJvYWRDYXN0KGNoYXIqKiBtYXRyaXgpIHsKICAgICAgICBpbnQgaTMgPSAwOwogICAgICAgIHdoaWxlIChpMyA8IFJPV1MpIHsKICAgICAgICAgICAgTVBJX0JjYXN0KG1hdHJpeFtpM10sIENPTFVNTlMsIE1QSV9DSEFSLCAwLCBNUElfQ09NTV9XT1JMRCk7CiAgICAgICAgICAgIGkzKys7CiAgICAgICAgfQp9Cgp2b2lkIEZyZWUoY2hhcioqIG1hdHJpeCl7CiAgICBpbnQgaTUgPSAwOwogICAgd2hpbGUgKGk1IDwgUk9XUykgewogICAgICAgIGZyZWUobWF0cml4W2k1XSk7CiAgICAgICAgaTUrKzsKICAgIH0KICAgIGZyZWUobWF0cml4KTsKfQoKY2hhcioqIGFsbG9OZ2VuTWF0cml4KGludCByYW5rKXsKICAgIGNoYXIgKiptYXRyaXggPSAoY2hhciAqKiltYWxsb2MoUk9XUyAqIHNpemVvZihjaGFyICopKTsKICAgIGludCBpMSA9IDA7CiAgICB3aGlsZSAoaTEgPCBST1dTKSB7CiAgICAgICAgbWF0cml4W2kxXSA9IChjaGFyKikgbWFsbG9jKENPTFVNTlMgKiBzaXplb2YoY2hhcikpOwogICAgICAgIGkxKys7CiAgICB9CiAgICBpZiAocmFuayA9PSAwKSB7CiAgICAgICAgc3JhbmQodGltZShOVUxMKSk7CiAgICAgICAgaW50IGkyID0gMDsKICAgICAgICB3aGlsZSAoaTIgPCBST1dTKSB7CiAgICAgICAgICAgIGludCBqMSA9IDA7CiAgICAgICAgICAgIHdoaWxlIChqMSA8IENPTFVNTlMpIHsKICAgICAgICAgICAgICAgIG1hdHJpeFtpMl1bajFdID0gKHJhbmQoKSAlIDI2KSArICdBJzsKICAgICAgICAgICAgICAgIGoxKys7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaTIrKzsKICAgICAgICB9CgogICAgfQogICAgcmV0dXJuIG1hdHJpeDsKfQoKdm9pZCBmaW5kUGFsaW5kcm9tZShpbnQgcmFuaywgY2hhcioqIG1hdHJpeCwgaW50IGxlbmd0aCwgaW50IHNpemUpewogICAgZG91YmxlIHN0YXJ0X3RpbWUgPSBNUElfV3RpbWUoKTsKICAgIGludCBsb2NhbF9jb3VudCA9IDAsIGdsb2JhbF9jb3VudCA9IDAsIGk0ID0gcmFuazsKICAgIHdoaWxlIChpNCA8IFJPV1MpIHsKICAgICAgICBmb3IgKGludCBqID0gMDsgaiA8IENPTFVNTlM7IGorKykgewogICAgICAgICAgICBsb2NhbF9jb3VudCArPSBjb3VudFBhTCgoY29uc3QgY2hhciAqKiltYXRyaXgsIGk0LCBqLCBsZW5ndGgpOwogICAgICAgIH0KICAgICAgICBpNCArPSBzaXplOwogICAgfQogICAgTVBJX1JlZHVjZSgmbG9jYWxfY291bnQsICZnbG9iYWxfY291bnQsIDEsIE1QSV9JTlQsIE1QSV9TVU0sIDAsIE1QSV9DT01NX1dPUkxEKTsKICAgIGRvdWJsZSBlbmRfdGltZSA9IE1QSV9XdGltZSgpOwogICAgaWYgKHJhbmsgPT0gMCkgewogICAgICAgIHByaW50ZigiJWQgcGFsaW5kcm9tZXMgb2Ygc2l6ZSAlZCBmb3VuZCBpbiAlbGYgcy4gdXNpbmcgJWQgcHJvY2Vzc2VzLlxuIiwKICAgICAgICAgICAgZ2xvYmFsX2NvdW50LCBsZW5ndGgsIGVuZF90aW1lIC0gc3RhcnRfdGltZSwgc2l6ZSk7CiAgICB9Cn0KCmludCBtYWluKGludCBhcmdjLCBjaGFyICphcmd2W10pIHsKICAgIGludCByYW5rLCBzaXplOwogICAgTVBJX0luaXQoJmFyZ2MsICZhcmd2KTsKICAgIE1QSV9Db21tX3JhbmsoTVBJX0NPTU1fV09STEQsICZyYW5rKTsKICAgIE1QSV9Db21tX3NpemUoTVBJX0NPTU1fV09STEQsICZzaXplKTsKCiAgICAvLyBBbGxvY2F0ZSBhbmQgZ2VuZXJhdGUgbWF0cml4CiAgICBjaGFyKiogbWF0cml4ID0gYWxsb05nZW5NYXRyaXgocmFuayk7CiAgICAvLyBCcm9hZGNhc3QgbWF0cml4IHRvIGFsbCBwcm9jZXNzZXMKICAgIGJyb2FkQ2FzdChtYXRyaXgpOwogICAgTVBJX0JhcnJpZXIoTVBJX0NPTU1fV09STEQpOwoKICAgIGZvciAoaW50IGxlbmd0aCAgPSAzOyBsZW5ndGggPCA3OyArKyBsZW5ndGgpIHsKICAgICAgICBmaW5kUGFsaW5kcm9tZShyYW5rLCBtYXRyaXgsIGxlbmd0aCwgc2l6ZSk7CiAgICB9CiAgICBpZiAocmFuayA9PSAwKSB7CiAgICAgICAgcHJpbnRmKCI9PT09PT09PT09PT09PT09PT09PT09PT09PT09PSoqKioqKioqKioqPT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiIpOwogICAgfQogICAgCiAgIAogICAgRnJlZShtYXRyaXgpOwogICAgTVBJX0ZpbmFsaXplKCk7CgogICAgcmV0dXJuIDA7Cn0=