Files
supercomputers/src/csv_loader.cpp

136 lines
4.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "csv_loader.hpp"
#include <fstream>
#include <sstream>
#include <iostream>
#include <stdexcept>
bool parse_csv_line(const std::string& line, Record& record) {
if (line.empty()) {
return false;
}
std::stringstream ss(line);
std::string item;
try {
// timestamp
if (!std::getline(ss, item, ',') || item.empty()) return false;
record.timestamp = std::stod(item);
// open
if (!std::getline(ss, item, ',') || item.empty()) return false;
record.open = std::stod(item);
// high
if (!std::getline(ss, item, ',') || item.empty()) return false;
record.high = std::stod(item);
// low
if (!std::getline(ss, item, ',') || item.empty()) return false;
record.low = std::stod(item);
// close
if (!std::getline(ss, item, ',') || item.empty()) return false;
record.close = std::stod(item);
// volume
if (!std::getline(ss, item, ',')) return false;
// Volume может быть пустым или содержать данные
if (item.empty()) {
record.volume = 0.0;
} else {
record.volume = std::stod(item);
}
return true;
} catch (const std::exception&) {
return false;
}
}
std::vector<Record> load_csv_parallel(int rank, int size) {
std::vector<Record> data;
// Читаем настройки из переменных окружения
std::string data_path = get_data_path();
std::vector<int> shares = get_data_read_shares();
int64_t overlap_bytes = get_read_overlap_bytes();
// Получаем размер файла
int64_t file_size = get_file_size(data_path);
// Вычисляем диапазон байт для этого ранка
ByteRange range = calculate_byte_range(rank, size, file_size, shares, overlap_bytes);
// Открываем файл и читаем нужный диапазон
std::ifstream file(data_path, std::ios::binary);
if (!file.is_open()) {
throw std::runtime_error("Cannot open file: " + data_path);
}
// Переходим к началу диапазона
file.seekg(range.start);
// Читаем данные в буфер
int64_t bytes_to_read = range.end - range.start;
std::vector<char> buffer(bytes_to_read);
file.read(buffer.data(), bytes_to_read);
int64_t bytes_read = file.gcount();
file.close();
// Преобразуем в строку для удобства парсинга
std::string content(buffer.data(), bytes_read);
// Находим позицию начала первой полной строки
size_t parse_start = 0;
if (rank == 0) {
// Первый ранк: пропускаем заголовок (первую строку)
size_t header_end = content.find('\n');
if (header_end != std::string::npos) {
parse_start = header_end + 1;
}
} else {
// Остальные ранки: начинаем с первого \n (пропускаем неполную строку)
size_t first_newline = content.find('\n');
if (first_newline != std::string::npos) {
parse_start = first_newline + 1;
}
}
// Находим позицию конца последней полной строки
size_t parse_end = content.size();
if (rank != size - 1) {
// Не последний ранк: ищем последний \n
size_t last_newline = content.rfind('\n');
if (last_newline != std::string::npos && last_newline > parse_start) {
parse_end = last_newline;
}
}
// Парсим строки
size_t pos = parse_start;
while (pos < parse_end) {
size_t line_end = content.find('\n', pos);
if (line_end == std::string::npos || line_end > parse_end) {
line_end = parse_end;
}
std::string line = content.substr(pos, line_end - pos);
// Убираем \r если есть (Windows line endings)
if (!line.empty() && line.back() == '\r') {
line.pop_back();
}
Record record;
if (parse_csv_line(line, record)) {
data.push_back(record);
}
pos = line_end + 1;
}
return data;
}