Files
FAT-Allocator/benchmarks/benchmarks/matrix_multiply/matrix_multiply-pthread.c
2024-11-07 17:09:42 +00:00

321 lines
8.9 KiB
C

/* Copyright (c) 2007-2009, Stanford University
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Stanford University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <strings.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <ctype.h>
#include <time.h>
#include <pthread.h>
#include <inttypes.h>
#include "map_reduce.h"
#include "stddefines.h"
#include "coz.h"
// #define malloc MALLOCCHERI
// #define free FREECHERI
typedef struct {
int row_num;
int *matrix_A;
int *matrix_B;
int matrix_len;
int *output;
} mm_data_t;
typedef struct {
int x_loc;
int y_loc;
int value;
} mm_key_t;
void *matrixmult_map(void *args_in);
/** matrixmul_splitter()
* Assign a set of rows of the output matrix to each thread
*/
void matrixmult_splitter(void *data_in)
{
pthread_attr_t attr;
pthread_t * tid;
int i, num_procs;
/* Make a copy of the mm_data structure */
mm_data_t * data = (mm_data_t *)data_in;
/* Check whether the various terms exist */
assert(data_in);
assert(data->matrix_len >= 0);
assert(data->matrix_A);
assert(data->matrix_B);
assert(data->output);
CHECK_ERROR((num_procs = sysconf(_SC_NPROCESSORS_ONLN)) <= 0);
dprintf("THe number of processors is %d\n", num_procs);
tid = (pthread_t *)malloc(num_procs * sizeof(pthread_t));
/* Thread must be scheduled systemwide */
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
int req_rows = data->matrix_len / num_procs;
for(i=0; i<num_procs; i++)
{
map_args_t* out = (map_args_t*)malloc(sizeof(map_args_t));
mm_data_t* data_out = (mm_data_t*)malloc(sizeof(mm_data_t));
memcpy(data_out,data, sizeof(mm_data_t));
int available_rows = data->matrix_len - data->row_num;
out->length = (req_rows < available_rows)? req_rows:available_rows;
out->data = data_out;
if(i == (num_procs - 1))
out->length = data->matrix_len - i*req_rows;
data->row_num += out->length;
dprintf("Allocated rows is % data->row_num is %d\n",out->length, data->row_num);
fflush(stdout);
CHECK_ERROR(pthread_create(&tid[i], &attr, matrixmult_map, (void*)out) != 0);
}
dprintf("outer loop \n");
/* Barrier, wait for all threads to finish */
for (i = 0; i < num_procs; i++)
{
dprintf("Inner loop \n");
// int ret_val;
// CHECK_ERROR(pthread_join(tid[i], (void **)(void*)&ret_val) != 0);
// CHECK_ERROR(ret_val != 0);
}
dprintf("Free step \n");
free(tid);
}
/** matrixmul_map()
* Function that computes the products for each of the portions assigned to the thread
*/
void *matrixmult_map(void *args_in)
{
map_args_t* args = (map_args_t*)args_in;
int row_count = 0;
int i,j, x_loc, y_loc, value;
int * a_ptr,* b_ptr;
assert(args);
mm_data_t* data = (mm_data_t*)(args->data);
assert(data);
while(row_count < args->length)
{
a_ptr = data->matrix_A + (data->row_num + row_count)*data->matrix_len;
for(i=0; i < data->matrix_len ; i++)
{
b_ptr = data->matrix_B + i;
value = 0;
for(j=0;j<data->matrix_len ; j++)
{
value += ( a_ptr[j] * (*b_ptr));
b_ptr+= data->matrix_len;
}
x_loc = (data->row_num + row_count);
y_loc = i;
//printf("THe location is %d %d, value is %d\n",x_loc, y_loc, value);
data->output[x_loc*data->matrix_len + i] = value;
COZ_PROGRESS;
}
row_count++;
}
free(args->data);
free(args);
return (void *)0;
}
int main(int argc, char *argv[]) {
//INITAlloc();
//INITREGULARALLOC();
int i,j, create_files;
int fd_A, fd_B, fd_out,file_size;
char * fdata_A, *fdata_B;
int matrix_len;
struct stat finfo_A, finfo_B;
char fname_A[512], fname_B[512], fname_out[512];
int *matrix_A_ptr, *matrix_B_ptr;
struct timeval starttime,endtime;
srand( (unsigned)time( NULL ) );
// Make sure a filename is specified
if (argv[1] == NULL)
{
printf("USAGE: %s size_of_matrix [-create_files]\n", argv[0]);
exit(1);
}
CHECK_ERROR ( (matrix_len = atoi(argv[1])) < 0);
sprintf(fname_A, "matrix_file_A_%d.txt", matrix_len);
sprintf(fname_B, "matrix_file_B_%d.txt", matrix_len);
sprintf(fname_out, "matrix_file_out_pthreads_%d.txt", matrix_len);
file_size = ((matrix_len*matrix_len))*sizeof(int);
fprintf(stderr, "***** file size is %d\n", file_size);
if(argv[2] != NULL)
create_files = 1;
else
create_files = 0;
printf("MatrixMult_pthreads: Side of the matrix is %d\n", matrix_len);
printf("MatrixMult_pthreads: Running...\n");
CHECK_ERROR((fd_out = open(fname_out,O_CREAT | O_RDWR,S_IRWXU)) < 0);
/* If the matrix files do not exist, create them */
if(create_files)
{
dprintf("Creating files\n");
int value = 0;
CHECK_ERROR((fd_A = open(fname_A,O_CREAT | O_RDWR,S_IRWXU)) < 0);
CHECK_ERROR((fd_B = open(fname_B,O_CREAT | O_RDWR,S_IRWXU)) < 0);
for(i=0;i<matrix_len;i++)
{
for(j=0;j<matrix_len;j++)
{
value = (rand())%11;
write(fd_A,&value,sizeof(int));
dprintf("%d ",value);
}
dprintf("\n");
}
dprintf("\n");
for(i=0;i<matrix_len;i++)
{
for(j=0;j<matrix_len;j++)
{
value = (rand())%11;
write(fd_B,&value,sizeof(int));
dprintf("%d ",value);
}
dprintf("\n");
}
CHECK_ERROR(close(fd_A) < 0);
CHECK_ERROR(close(fd_B) < 0);
}
// Read in the file
CHECK_ERROR((fd_A = open(fname_A,O_RDONLY)) < 0);
// Get the file info (for file length)
CHECK_ERROR(fstat(fd_A, &finfo_A) < 0);
// Memory map the file
CHECK_ERROR((fdata_A= (char*)mmap(0, file_size + 1,
PROT_READ | PROT_WRITE, MAP_PRIVATE, fd_A, 0)) == NULL);
// Read in the file
CHECK_ERROR((fd_B = open(fname_B,O_RDONLY)) < 0);
// Get the file info (for file length)
CHECK_ERROR(fstat(fd_B, &finfo_B) < 0);
// Memory map the file
CHECK_ERROR((fdata_B= (char*)mmap(0, file_size + 1,
PROT_READ | PROT_WRITE, MAP_PRIVATE, fd_B, 0)) == NULL);
// Setup splitter args
mm_data_t mm_data;
mm_data.matrix_len = matrix_len;
mm_data.matrix_A = NULL;
mm_data.matrix_B = NULL;
mm_data.row_num = 0;
mm_data.output = (int*)malloc(matrix_len*matrix_len*sizeof(int));
mm_data.matrix_A = matrix_A_ptr = ((int *)fdata_A);
mm_data.matrix_B = matrix_B_ptr = ((int *)fdata_B);
printf("MatrixMult_pthreads: Calling MapReduce Scheduler Matrix Multiplication\n");
gettimeofday(&starttime,0);
matrixmult_splitter(&mm_data);
gettimeofday(&endtime,0);
size_t start_usec = starttime.tv_sec * 1000000 + starttime.tv_usec;
size_t end_usec = endtime.tv_sec * 1000000 + endtime.tv_usec;
float usec = end_usec - start_usec;
fprintf(stderr, "runtime = %f\n", (usec / 1000000));
for(i=0;i<matrix_len*matrix_len;i++)
{
if(i%matrix_len == 0)
dprintf("\n");
dprintf("%d ",mm_data.output[i]);
write(fd_out,&(mm_data.output[i]),sizeof(int));
}
dprintf("\n");
dprintf("MatrixMult_pthreads: MapReduce Completed\n");
free(mm_data.output);
CHECK_ERROR(munmap(fdata_A, file_size + 1) < 0);
CHECK_ERROR(close(fd_A) < 0);
CHECK_ERROR(munmap(fdata_B, file_size + 1) < 0);
CHECK_ERROR(close(fd_B) < 0);
CHECK_ERROR(close(fd_out) < 0);
return 0;
}