2023-10-08 00:49:58 +00:00
|
|
|
#include <math.h>
|
|
|
|
#include <omp.h>
|
2023-10-06 06:21:15 +00:00
|
|
|
#include <stdio.h>
|
2023-10-08 00:49:58 +00:00
|
|
|
#include <stdlib.h>
|
2023-10-08 01:37:18 +00:00
|
|
|
#include <string.h>
|
2023-10-06 06:21:15 +00:00
|
|
|
|
2023-09-23 05:04:06 +00:00
|
|
|
#include "common.h"
|
|
|
|
|
2023-10-06 06:21:15 +00:00
|
|
|
int main(int argc, char **argv) {
|
2023-10-09 07:51:38 +00:00
|
|
|
if (argc < 5) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"USAGE: %s data_file label_file outer_iterations thread_count",
|
|
|
|
argv[0]);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2023-10-06 06:21:15 +00:00
|
|
|
char *data_file_name = argv[1], *label_file_name = argv[2];
|
2023-10-08 00:49:58 +00:00
|
|
|
int outer_iterations = atoi(argv[3]);
|
|
|
|
int thread_count = atoi(argv[4]);
|
|
|
|
|
2023-10-08 01:37:18 +00:00
|
|
|
omp_set_num_threads(thread_count);
|
2023-10-06 06:21:15 +00:00
|
|
|
|
|
|
|
struct data *data = read_data(data_file_name);
|
2023-10-09 08:49:21 +00:00
|
|
|
struct labels *labels = read_labels(label_file_name);
|
2023-10-09 07:51:38 +00:00
|
|
|
|
2023-10-09 08:49:21 +00:00
|
|
|
FLOAT *w = calloc(data->dimensions, sizeof(FLOAT));
|
|
|
|
FLOAT *new_w = calloc(data->dimensions, sizeof(FLOAT));
|
|
|
|
FLOAT *inner_calc = calloc(data->dimensions * data->rows, sizeof(FLOAT));
|
2023-10-09 07:51:38 +00:00
|
|
|
|
2023-10-08 00:49:58 +00:00
|
|
|
printf("Running %d iteration(s) with %d thread(s).\n", outer_iterations,
|
|
|
|
thread_count);
|
2023-10-09 08:14:23 +00:00
|
|
|
double program_start_time = monotonic_seconds();
|
2023-10-08 00:49:58 +00:00
|
|
|
|
2023-10-09 08:14:23 +00:00
|
|
|
double total_compute_time = 0;
|
2023-10-08 00:49:58 +00:00
|
|
|
for (int iter = 0; iter < outer_iterations; iter++) {
|
2023-10-09 08:14:23 +00:00
|
|
|
double iter_start_time = monotonic_seconds();
|
2023-10-08 00:49:58 +00:00
|
|
|
|
|
|
|
#pragma omp parallel for default(shared)
|
|
|
|
for (int i = 0; i < data->dimensions; i++) {
|
|
|
|
|
2023-10-09 09:30:22 +00:00
|
|
|
#pragma omp parallel for default(shared) if (thread_count > data->dimensions)
|
2023-10-08 00:49:58 +00:00
|
|
|
for (int j = 0; j < data->rows; j++) {
|
|
|
|
FLOAT x_ni_w_ni = 0;
|
|
|
|
|
2023-10-09 07:51:38 +00:00
|
|
|
// #pragma omp parallel for default(shared) reduction(+ : x_ni_w_ni)
|
2023-10-08 00:49:58 +00:00
|
|
|
for (int i2 = 0; i2 < data->dimensions; i2++) {
|
|
|
|
if (i2 == i)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
x_ni_w_ni = data->buf[data->rows * i2 + j] * w[i2];
|
|
|
|
}
|
|
|
|
|
2023-10-09 08:49:21 +00:00
|
|
|
inner_calc[data->rows * i + j] = labels->buf[j] - x_ni_w_ni;
|
2023-10-08 00:49:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FLOAT numer = 0, denom = 0;
|
|
|
|
|
2023-10-09 07:51:38 +00:00
|
|
|
// #pragma omp parallel for default(shared) reduction(+ : numer, denom)
|
2023-10-09 09:30:22 +00:00
|
|
|
// if(thread_count > data->dimensions)
|
2023-10-08 00:49:58 +00:00
|
|
|
for (int j = 0; j < data->rows; j++) {
|
2023-10-09 07:51:38 +00:00
|
|
|
FLOAT xij = data->buf[data->rows * i + j];
|
2023-10-09 08:49:21 +00:00
|
|
|
numer += xij * inner_calc[data->rows * i + j];
|
2023-10-09 07:51:38 +00:00
|
|
|
denom += xij * xij;
|
2023-10-08 00:49:58 +00:00
|
|
|
}
|
|
|
|
|
2023-10-09 08:14:23 +00:00
|
|
|
if (denom == 0)
|
2023-10-09 07:51:38 +00:00
|
|
|
new_w[i] = 0;
|
2023-10-09 08:14:23 +00:00
|
|
|
else
|
2023-10-09 07:51:38 +00:00
|
|
|
new_w[i] = numer / denom;
|
2023-10-08 00:49:58 +00:00
|
|
|
}
|
|
|
|
|
2023-10-09 08:14:23 +00:00
|
|
|
double iter_end_time = monotonic_seconds();
|
|
|
|
total_compute_time += iter_end_time - iter_start_time;
|
|
|
|
printf("Iter duration (no print): %0.04fs\n",
|
|
|
|
iter_end_time - iter_start_time);
|
2023-10-09 07:51:38 +00:00
|
|
|
|
2023-10-09 08:14:23 +00:00
|
|
|
// Update w
|
|
|
|
// printf("w = [");
|
2023-10-08 00:49:58 +00:00
|
|
|
for (int idx = 0; idx < data->dimensions; idx++) {
|
2023-10-09 07:51:38 +00:00
|
|
|
w[idx] = new_w[idx];
|
2023-10-09 08:14:23 +00:00
|
|
|
// printf("%.3f ", w[idx]);
|
2023-10-08 00:49:58 +00:00
|
|
|
}
|
2023-10-09 08:14:23 +00:00
|
|
|
// printf("]\n");
|
|
|
|
|
|
|
|
// Compute loss
|
|
|
|
FLOAT loss_sum = 0;
|
|
|
|
#pragma omp parallel for default(shared)
|
|
|
|
for (int j = 0; j < data->rows; j++) {
|
|
|
|
FLOAT loss_value = 0;
|
|
|
|
for (int i = 0; i < data->dimensions; i++) {
|
|
|
|
loss_value += data->buf[data->rows * i + j] * w[i];
|
|
|
|
}
|
|
|
|
|
2023-10-09 08:49:21 +00:00
|
|
|
loss_value -= labels->buf[j];
|
2023-10-09 08:14:23 +00:00
|
|
|
loss_sum += loss_value * loss_value;
|
|
|
|
}
|
|
|
|
FLOAT loss = sqrt(loss_sum);
|
|
|
|
printf("Loss: %0.04f\n", loss);
|
2023-10-08 00:49:58 +00:00
|
|
|
|
2023-10-09 07:51:38 +00:00
|
|
|
// memcpy(w, new_w, data->dimensions * sizeof(FLOAT));
|
2023-10-08 00:49:58 +00:00
|
|
|
}
|
|
|
|
|
2023-10-09 08:14:23 +00:00
|
|
|
double program_end_time = monotonic_seconds();
|
|
|
|
printf("Program time (compute): %0.04fs\n", total_compute_time);
|
|
|
|
printf("Program time (total): %0.04fs\n",
|
|
|
|
program_end_time - program_start_time);
|
|
|
|
|
|
|
|
// free(loss_matrix);
|
2023-10-09 08:49:21 +00:00
|
|
|
free(inner_calc);
|
2023-10-08 01:37:18 +00:00
|
|
|
free(new_w);
|
|
|
|
free(data->buf);
|
2023-10-09 08:49:21 +00:00
|
|
|
free(labels->buf);
|
2023-10-08 01:37:18 +00:00
|
|
|
free(data);
|
2023-10-09 08:49:21 +00:00
|
|
|
free(labels);
|
2023-10-06 06:21:15 +00:00
|
|
|
|
2023-10-09 07:51:38 +00:00
|
|
|
// NOTE: NOT PART OF THE ASSIGNMENT
|
2023-10-09 08:49:21 +00:00
|
|
|
// Perform validation to see how well the model performs on training data
|
2023-10-09 07:51:38 +00:00
|
|
|
|
|
|
|
if (argc >= 7) {
|
|
|
|
struct data *test_data = read_data(argv[5]);
|
|
|
|
struct labels *test_label = read_labels(argv[6]);
|
|
|
|
|
|
|
|
int num_correct = 0;
|
|
|
|
for (int j = 0; j < test_data->rows; j++) {
|
|
|
|
FLOAT output = 0;
|
|
|
|
for (int i = 0; i < test_data->dimensions; i++) {
|
|
|
|
output += test_data->buf[test_data->rows * i + j] * w[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
FLOAT correct_answer = test_label->buf[j];
|
|
|
|
FLOAT incorrect_answer = -correct_answer;
|
|
|
|
|
|
|
|
if (fabs(output - correct_answer) < fabs(output - incorrect_answer))
|
|
|
|
num_correct += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("num correct: %d, out of %d (%.2f%%)\n", num_correct,
|
|
|
|
test_data->rows, (100.0 * num_correct) / test_data->rows);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(w);
|
|
|
|
|
2023-10-06 06:21:15 +00:00
|
|
|
return 0;
|
|
|
|
}
|