lol
This commit is contained in:
185
benchmark.c
Normal file
185
benchmark.c
Normal file
@@ -0,0 +1,185 @@
|
||||
#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);
|
||||
}
|
||||
Reference in New Issue
Block a user