Initial commit

This commit is contained in:
Dmitriy Shishkov 2025-04-13 00:43:03 +03:00
commit e8f43940ac
Signed by: dm1sh
GPG Key ID: 027994B0AA357688
7 changed files with 350 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
.cache/
.venv/
.vscode/
build/

11
CMakeLists.txt Normal file
View File

@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.26)
project(filter)
set(CMAKE_CXX_STANDARD 17)
find_package(OpenCL REQUIRED)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} PUBLIC ${OpenCL_LIBRARIES})
target_include_directories(${PROJECT_NAME} PUBLIC ${OpenCL_INCLUDE_DIRS})

1
filter_coefs.bin Normal file
View File

@ -0,0 +1 @@
a=J>š¿P[?‡ik¾ Ûf?M3¿Æ7?Klü¾pÞ<70>?êý>>÷Z?¤ž¸>q,?,M¿ø>

BIN
input_file.bin Normal file

Binary file not shown.

147
main.cpp Normal file
View File

@ -0,0 +1,147 @@
#include <cstdint>
#include <fstream>
#ifdef __unix__
#include "CL/opencl.hpp"
#endif
#ifdef _WIN32
#include "CL/cl.hpp"
#endif
#include <filesystem>
#include <iostream>
#include <vector>
struct finfo {
char *fname;
std::uintmax_t fsize;
size_t flength;
};
std::vector<float> read_file(char *fname) {
auto fsize = std::filesystem::file_size(fname);
if (fsize % sizeof(float) != 0) {
std::cerr << fname << " size is not a multiple of float size" << std::endl;
exit(1);
}
size_t flength = fsize / sizeof(float);
std::ifstream file(fname, std::ios::binary);
if (!file) {
std::cerr << "Failed to open " << fname << std::endl;
exit(1);
}
std::vector<float> vec(flength);
file.read(reinterpret_cast<char *>(vec.data()), fsize);
if (!file) {
std::cerr << "Failed to read " << fname << std::endl;
exit(1);
}
return vec;
}
void write_file(std::vector<float> vec, char *fname) {
std::ofstream file(fname, std::ios::binary);
if (!file) {
std::cerr << "Failed to open " << fname << std::endl;
exit(1);
}
file.write(reinterpret_cast<char *>(vec.data()), sizeof(float) * vec.size());
if (!file) {
std::cerr << "Failed to write " << fname << std::endl;
exit(1);
}
}
int main(int argc, char *argv[]) {
if (argc != 4) {
std::cerr << "Two input and one output files must be provided:"
<< std::endl;
std::cerr << "./filter input_file.bin filter_coefs.bin output_file.bin"
<< std::endl;
exit(1);
}
// Исходные данные
std::vector<float> input_file = read_file(argv[1]);
std::vector<float> filter_coefs = read_file(argv[2]);
size_t output_length = input_file.size() - filter_coefs.size() + 1;
std::vector<float> output_file(output_length);
// Получаем платформы и устройства
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
cl::Device device;
for (const auto &platform : platforms) {
std::vector<cl::Device> devices;
platform.getDevices(CL_DEVICE_TYPE_CPU, &devices);
if (!devices.empty()) {
device = devices.front();
break;
}
}
// Создаем контекст и очередь команд
cl::Context context(device);
cl::CommandQueue queue(context, device);
// Выделяем память на GPU
cl::Buffer input_buffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
sizeof(float) * input_file.size(), input_file.data());
cl::Buffer filter_buffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
sizeof(float) * filter_coefs.size(),
filter_coefs.data());
cl::Buffer output_buffer(context, CL_MEM_WRITE_ONLY,
sizeof(float) * output_file.size());
// Компилируем ядро
const char *kernel_code = R"(
__kernel void convolve(__constant const float *input,
__constant const float *filter, __global float *output,
const int filter_length) {
int id = get_global_id(0);
float sum = 0.0f;
for (int i = 0; i < filter_length; ++i) {
const int input_pos = id - i + filter_length - 1;
sum += input[input_pos] * filter[i];
}
output[id] = sum;
}
)";
cl::Program program(context, kernel_code);
program.build("-cl-std=CL1.2");
// Создаем ядро и устанавливаем аргументы
cl::Kernel kernel(program, "convolve");
kernel.setArg(0, input_buffer);
kernel.setArg(1, filter_buffer);
kernel.setArg(2, output_buffer);
kernel.setArg(3, static_cast<int>(filter_coefs.size()));
// Запускаем ядро
queue.enqueueNDRangeKernel(kernel, cl::NullRange, cl::NDRange(output_length),
cl::NullRange);
// Копируем результат обратно на CPU
queue.enqueueReadBuffer(output_buffer, CL_TRUE, 0,
sizeof(float) * output_length, output_file.data());
// Выводим результат
for (float c : output_file) {
std::cout << c << " ";
}
write_file(output_file, argv[3]);
return 0;
}

BIN
output_file.bin Normal file

Binary file not shown.

187
test.ipynb Normal file

File diff suppressed because one or more lines are too long