134 lines
3.5 KiB
C++
134 lines
3.5 KiB
C++
#include "gpu_loader.hpp"
|
||
#include <dlfcn.h>
|
||
#include <iostream>
|
||
#include <cstdint>
|
||
|
||
// Структура результата GPU (должна совпадать с gpu_plugin.cu)
|
||
struct GpuPeriodStats {
|
||
int64_t period;
|
||
double avg;
|
||
double open_min;
|
||
double open_max;
|
||
double close_min;
|
||
double close_max;
|
||
int64_t count;
|
||
};
|
||
|
||
// Типы функций из GPU плагина
|
||
using gpu_is_available_fn = int (*)();
|
||
|
||
using gpu_aggregate_periods_fn = int (*)(
|
||
const double* h_timestamps,
|
||
const double* h_open,
|
||
const double* h_high,
|
||
const double* h_low,
|
||
const double* h_close,
|
||
int num_ticks,
|
||
int64_t interval,
|
||
GpuPeriodStats** h_out_stats,
|
||
int* out_num_periods
|
||
);
|
||
|
||
using gpu_free_results_fn = void (*)(GpuPeriodStats*);
|
||
|
||
static void* get_gpu_lib_handle() {
|
||
static void* h = dlopen("./libgpu_compute.so", RTLD_NOW | RTLD_LOCAL);
|
||
return h;
|
||
}
|
||
|
||
bool gpu_is_available() {
|
||
void* h = get_gpu_lib_handle();
|
||
if (!h) return false;
|
||
|
||
auto fn = reinterpret_cast<gpu_is_available_fn>(dlsym(h, "gpu_is_available"));
|
||
if (!fn) return false;
|
||
|
||
return fn() != 0;
|
||
}
|
||
|
||
bool aggregate_periods_gpu(
|
||
const std::vector<Record>& records,
|
||
int64_t aggregation_interval,
|
||
std::vector<PeriodStats>& out_stats)
|
||
{
|
||
if (records.empty()) {
|
||
out_stats.clear();
|
||
return true;
|
||
}
|
||
|
||
void* h = get_gpu_lib_handle();
|
||
if (!h) {
|
||
std::cerr << "GPU: Failed to load libgpu_compute.so" << std::endl;
|
||
return false;
|
||
}
|
||
|
||
auto aggregate_fn = reinterpret_cast<gpu_aggregate_periods_fn>(
|
||
dlsym(h, "gpu_aggregate_periods"));
|
||
auto free_fn = reinterpret_cast<gpu_free_results_fn>(
|
||
dlsym(h, "gpu_free_results"));
|
||
|
||
if (!aggregate_fn || !free_fn) {
|
||
std::cerr << "GPU: Failed to load functions from plugin" << std::endl;
|
||
return false;
|
||
}
|
||
|
||
int num_ticks = static_cast<int>(records.size());
|
||
|
||
// Конвертируем AoS в SoA
|
||
std::vector<double> timestamps(num_ticks);
|
||
std::vector<double> open(num_ticks);
|
||
std::vector<double> high(num_ticks);
|
||
std::vector<double> low(num_ticks);
|
||
std::vector<double> close(num_ticks);
|
||
|
||
for (int i = 0; i < num_ticks; i++) {
|
||
timestamps[i] = records[i].timestamp;
|
||
open[i] = records[i].open;
|
||
high[i] = records[i].high;
|
||
low[i] = records[i].low;
|
||
close[i] = records[i].close;
|
||
}
|
||
|
||
// Вызываем GPU функцию
|
||
GpuPeriodStats* gpu_stats = nullptr;
|
||
int num_periods = 0;
|
||
|
||
int result = aggregate_fn(
|
||
timestamps.data(),
|
||
open.data(),
|
||
high.data(),
|
||
low.data(),
|
||
close.data(),
|
||
num_ticks,
|
||
aggregation_interval,
|
||
&gpu_stats,
|
||
&num_periods
|
||
);
|
||
|
||
if (result != 0) {
|
||
std::cerr << "GPU: Aggregation failed with code " << result << std::endl;
|
||
return false;
|
||
}
|
||
|
||
// Конвертируем результат в PeriodStats
|
||
out_stats.clear();
|
||
out_stats.reserve(num_periods);
|
||
|
||
for (int i = 0; i < num_periods; i++) {
|
||
PeriodStats ps;
|
||
ps.period = gpu_stats[i].period;
|
||
ps.avg = gpu_stats[i].avg;
|
||
ps.open_min = gpu_stats[i].open_min;
|
||
ps.open_max = gpu_stats[i].open_max;
|
||
ps.close_min = gpu_stats[i].close_min;
|
||
ps.close_max = gpu_stats[i].close_max;
|
||
ps.count = gpu_stats[i].count;
|
||
out_stats.push_back(ps);
|
||
}
|
||
|
||
// Освобождаем память
|
||
free_fn(gpu_stats);
|
||
|
||
return true;
|
||
}
|