Files
graphe/benchmark.c
Tiago Batista Cardoso 2d3865079d lol
2026-02-28 22:41:19 +01:00

186 lines
5.1 KiB
C

#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include "benchmark.h"
#include "structs.h"
#include "algorithms.h"
#define NUM_SIZES 5
#define NUM_CONFIGS 5
#define TOTAL_GRAPHS 5
static int graph_sizes[NUM_SIZES] = { 5, 10, 20, 100, 500 };
typedef struct {
int n;
double p;
double q;
int k;
int graph_index;
int config_index;
// results
double time_kclique;
double time_louvain;
double time_cbla;
int kclique_communities;
int louvain_communities;
int cbla_communities;
int done;
char error[128];
} bench_task_t;
static double elapsed_ms(struct timespec start, struct timespec end)
{
return ((end.tv_sec - start.tv_sec) * 1000.0) +
((end.tv_nsec - start.tv_nsec) / 1e6);
}
static void *benchmark_thread(void *arg)
{
bench_task_t *task = (bench_task_t *)arg;
struct timespec t0, t1;
printf("[thread] config=%d graph=%d n=%-7d p=%.2f q=%.2f — generating...\n",
task->config_index + 1, task->graph_index + 1, task->n, task->p,
task->q);
graph_t *graph = generate_graph(task->n, task->p, task->q, 122);
if (!graph) {
snprintf(task->error, sizeof(task->error),
"generate_graph failed");
task->done = 1;
return NULL;
}
clock_gettime(CLOCK_MONOTONIC, &t0);
community_result_t *kc = find_k_clique_communities(graph, task->k);
clock_gettime(CLOCK_MONOTONIC, &t1);
task->time_kclique = elapsed_ms(t0, t1);
task->kclique_communities = kc ? kc->count : 0;
free_community_result(kc);
clock_gettime(CLOCK_MONOTONIC, &t0);
louvain_result_t *lv = compute_louvain(graph);
clock_gettime(CLOCK_MONOTONIC, &t1);
task->time_louvain = elapsed_ms(t0, t1);
task->louvain_communities = lv ? lv->count : 0;
free_louvain_result(lv);
clock_gettime(CLOCK_MONOTONIC, &t0);
cbla_result_t *hy = cbla_community_detection(graph, task->k);
clock_gettime(CLOCK_MONOTONIC, &t1);
task->time_cbla = elapsed_ms(t0, t1);
task->cbla_communities = hy ? hy->count : 0;
free_cbla_result(hy);
free_graph(graph);
printf("[thread] config=%d graph=%d n=%-7d — done "
"(kclique=%.1fms louvain=%.1fms cbla=%.1fms)\n",
task->config_index + 1, task->graph_index + 1, task->n,
task->time_kclique, task->time_louvain, task->time_cbla);
task->done = 1;
return NULL;
}
void run_benchmark(void)
{
// p/q configurations
double configs[NUM_CONFIGS][3] = {
{ 1.0, 0.15, 3 }, { 1.0, 0.15, 3 }, { 0.8, 0.05, 3 },
{ 0.4, 0.02, 5 }, { 0.10, 0.005, 6 },
};
bench_task_t tasks[TOTAL_GRAPHS];
pthread_t threads[TOTAL_GRAPHS];
int task_idx = 0;
// Initialize all tasks
for (int c = 0; c < TOTAL_GRAPHS; c++) {
bench_task_t *t = &tasks[task_idx++];
t->n = graph_sizes[c];
t->p = configs[c][0];
t->q = configs[c][1];
t->k = configs[c][2];
t->config_index = c;
t->graph_index = c;
t->done = 0;
t->error[0] = '\0';
t->time_kclique = 0;
t->time_louvain = 0;
t->time_cbla = 0;
}
printf("[benchmark] launching %d threads...\n", TOTAL_GRAPHS);
// Launch one thread per task
for (int i = 0; i < TOTAL_GRAPHS; i++)
pthread_create(&threads[i], NULL, benchmark_thread, &tasks[i]);
// Wait for all threads
for (int i = 0; i < TOTAL_GRAPHS; i++)
pthread_join(threads[i], NULL);
printf("[benchmark] all threads done — writing CSV...\n");
// ── Build timestamped filename ────────────────────────────────────────────
time_t now = time(NULL);
struct tm *tm = localtime(&now);
char filename[64];
strftime(filename, sizeof(filename), "benchmark_%Y%m%d_%H%M%S.csv", tm);
// ── Write CSV ─────────────────────────────────────────────────────────────
FILE *f = fopen(filename, "w");
if (!f) {
perror("fopen");
return;
}
// Header
fprintf(f, "config,p,q,graph_size,"
"kclique_time_ms,kclique_communities,"
"louvain_time_ms,louvain_communities,"
"cbla_time_ms,cbla_communities\n");
char config_names[NUM_CONFIGS][32] = {
"very_dense", "dense", "medium", "sparse", "very_sparse",
};
task_idx = 0;
for (int i = 0; i < TOTAL_GRAPHS; i++) {
bench_task_t *t = &tasks[i];
char kclique_time[16], kclique_comm[16];
char cbla_time[16], cbla_comm[16];
if (t->time_kclique < 0) {
snprintf(kclique_time, sizeof(kclique_time), "N/A");
snprintf(kclique_comm, sizeof(kclique_comm), "N/A");
} else {
snprintf(kclique_time, sizeof(kclique_time), "%.4f",
t->time_kclique);
snprintf(kclique_comm, sizeof(kclique_comm), "%d",
t->kclique_communities);
}
if (t->time_cbla < 0) {
snprintf(cbla_time, sizeof(cbla_time), "N/A");
snprintf(cbla_comm, sizeof(cbla_comm), "N/A");
} else {
snprintf(cbla_time, sizeof(cbla_time), "%.4f",
t->time_cbla);
snprintf(cbla_comm, sizeof(cbla_comm), "%d",
t->cbla_communities);
}
fprintf(f, "%s,%.4f,%.6f,%d,%s,%s,%.4f,%d,%s,%s\n",
config_names[i], t->p, t->q, t->n, kclique_time,
kclique_comm, t->time_louvain, t->louvain_communities,
cbla_time, cbla_comm);
}
fclose(f);
printf("[benchmark] results written to %s\n", filename);
}