Initial commit
This commit is contained in:
commit
e8f43940ac
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
.cache/
|
||||
.venv/
|
||||
.vscode/
|
||||
build/
|
11
CMakeLists.txt
Normal file
11
CMakeLists.txt
Normal 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
1
filter_coefs.bin
Normal file
@ -0,0 +1 @@
|
||||
a=J>’š¿P[?‡ik¾ Ûf?M3¿Æ7?Klü¾pÞ<70>?êý>>÷Z?¤ž¸>q,?,M¿ø?œ>
|
BIN
input_file.bin
Normal file
BIN
input_file.bin
Normal file
Binary file not shown.
147
main.cpp
Normal file
147
main.cpp
Normal 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
BIN
output_file.bin
Normal file
Binary file not shown.
187
test.ipynb
Normal file
187
test.ipynb
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user