Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 173 additions & 0 deletions src/parallel.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <omp.h>

double getMax(const double *arr, int n);
double getMin(const double *arr, int n);
double getSum(const double *arr, int n);

void printUsage(const char *progName)
{
printf("Usage: %s <filename> <runs>\n", progName);
printf(" <filename> : Path to the input file (default: ../data/large.txt)\n");
printf(" <runs> : Number of runs to perform (default: 50)\n");
}

int main(int argc, char *argv[])
{

char *filename = "../data/large.txt"; // Adjust path if needed
int RUNS = 50;
if (argc > 1)
{
if (argc == 2 && strcmp(argv[1], "-h") == 0)
{
printUsage(argv[0]);
return 0;
}
if (argc >= 2)
{
filename = argv[1];
}
if (argc >= 3)
{
RUNS = atoi(argv[2]);
if (RUNS <= 0)
{
fprintf(stderr, "Invalid number of RUNS specified. Using default 50.\n");
RUNS = 50;
}
}
}

double min = 0.0;
double max = 0.0;
double sum = 0.0;
double avg = 0.0;
double *times = malloc(sizeof(double) * RUNS);
Copy link

Copilot AI Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing null check after malloc. If memory allocation fails, the program will crash when accessing times[count] at line 126.

Suggested change
double *times = malloc(sizeof(double) * RUNS);
double *times = malloc(sizeof(double) * RUNS);
if (!times)
{
perror("malloc");
return 1;
}

Copilot uses AI. Check for mistakes.

FILE *file = fopen(filename, "rb");
if (!file)
{
perror("Error opening file");
return 1;
}

if (fseek(file, 0, SEEK_END) != 0)
{
perror("fseek");
fclose(file);
return 1;
}
long file_size = ftell(file);
if (file_size < 0)
{
perror("ftell");
fclose(file);
return 1;
}
rewind(file);

char *buf = malloc((size_t)file_size + 1);
if (!buf)
{
perror("malloc");
fclose(file);
return 1;
}

size_t read = fread(buf, 1, (size_t)file_size, file);
buf[read] = '\0';
fclose(file);

long long total_words = 0;
int nthreads = 1;
for (int count = 0; count < RUNS; count++)
{
total_words = 0;
double t0 = omp_get_wtime();
#pragma omp parallel
{
int tid = omp_get_thread_num();
int nth = omp_get_num_threads();
#pragma omp single
nthreads = nth;

size_t chunk = (read + nth - 1) / nth; // ceil division
size_t start = tid * chunk;
size_t end = start + chunk;
if (end > read)
end = read;

long long local_count = 0;
for (size_t i = start; i < end; ++i)
{
unsigned char c = (unsigned char)buf[i];
if (!isspace(c))
{
if (i == 0)
{
local_count++;
}
else if (isspace((unsigned char)buf[i - 1]))
Copy link

Copilot AI Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out-of-bounds memory access when i == start and start > 0. Thread checks buf[i - 1] without verifying that i > start, which could access memory outside the thread's intended chunk range, potentially causing race conditions or incorrect results.

Suggested change
else if (isspace((unsigned char)buf[i - 1]))
else if (i > start && isspace((unsigned char)buf[i - 1]))

Copilot uses AI. Check for mistakes.
{
local_count++;
}
Comment on lines +110 to +117
Copy link

Copilot AI Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Word counting logic is incorrect for multi-threaded execution. Each thread checks if i == 0 to detect word start, but only thread 0 will have i == 0 as the actual start of the buffer. Other threads starting at start > 0 will incorrectly count a word at their chunk boundary if the character is non-space, even if it's in the middle of a word. This will lead to incorrect word counts.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback

}
}

#pragma omp atomic
total_words += local_count;
}

double t1 = omp_get_wtime();
times[count] = t1 - t0;
}
max = getMax(times, RUNS);
min = getMin(times, RUNS);
sum = getSum(times, RUNS);
avg = sum / RUNS;

printf("✅ File: %s\n", filename);
printf("Total words: %lld\n", total_words);
printf("Threads: %d\n", nthreads);
printf("max time: %.6f seconds\n", max);
printf("min time: %.6f seconds\n", min);
printf("avg time: %.6f seconds\n", avg);
printf("num of runs: %d\n", RUNS);
free(buf);
free(times);
Copy link

Copilot AI Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Memory leak: times array is freed even when malloc at line 49 might have failed (no null check). Additionally, if malloc fails and returns NULL, calling free(NULL) is safe but the program should have exited earlier.

Copilot uses AI. Check for mistakes.
return 0;
}

double getMax(const double *arr, int n)
{
if (n <= 0)
return 0.0;
double m = arr[0];
for (int i = 1; i < n; ++i)
if (arr[i] > m)
m = arr[i];
return m;
}

double getMin(const double *arr, int n)
{
if (n <= 0)
return 0.0;
double m = arr[0];
for (int i = 1; i < n; ++i)
if (arr[i] < m)
m = arr[i];
return m;
}

double getSum(const double *arr, int n)
{
double s = 0.0;
for (int i = 0; i < n; ++i)
s += arr[i];
return s;
}