Недавно я начал изучать OpenCL и пытался с его помощью преобразовать видеокадр RGBA в NV12.
Я заметил, что в диспетчере задач для такой легкой задачи отображается недопустимо высокий уровень использования 3D. , но не используется Copy/Copy1/Copy2.
При попытке внесения изменений я обнаружил, что это продолжает происходить даже при пустой функции ядра.
#define CL_HPP_ENABLE_EXCEPTIONS
#define CL_HPP_TARGET_OPENCL_VERSION 200
#include
#include
#include
#include
#include
int main() {
std::vector platdevlist;
std::vector platforms;
cl::Platform::get(&platforms);
for (auto& p : platforms) {
std::string platver = p.getInfo();
if (platver.find("OpenCL 2.") != std::string::npos ||
platver.find("OpenCL 3.") != std::string::npos)
{
cl::vector devices;
p.getDevices(CL_DEVICE_TYPE_ALL, &devices);
for (auto& d : devices) {
platdevlist.emplace_back(std::make_pair(p, d));
}
}
}
for(int i = 0; i < platdevlist.size(); ++i) {
fprintf(stderr, "%d: platform: %s, device: %s\n",
i,
platdevlist[i].first.getInfo().c_str(),
platdevlist[i].second.getInfo().c_str()
);
}
int selected_index;
fprintf(stderr, "select one: \n");
scanf("%d", &selected_index);
auto selected = platdevlist[selected_index];
auto ctx = cl::Context(cl::vector{ selected.second });
auto queue = cl::CommandQueue{ ctx, selected.second, cl::QueueProperties::None };
std::string sourcecode{ "kernel void empty(global char* dst, global const char* src) { }" };
auto program = cl::Program(ctx, {sourcecode});
try {
program.build("-cl-std=CL2.0");
}
catch (...) {
for (auto& pair : program.getBuildInfo()) {
fprintf(stderr, "%s", pair.second.c_str());
}
return 1;
}
auto func = cl::KernelFunctor(program, "empty");
std::vector srcbuf(2560 * 1440 * 4);
std::vector dstbuf(2560 * 1440 * 1.5);
cl::Buffer src(ctx, CL_MEM_READ_ONLY, (size_t)2560 * 1440 * 4);
cl::Buffer dst(ctx, CL_MEM_WRITE_ONLY, (size_t)2560 * 1440 * 1.5);
auto iter_count = 1;
auto begin = std::chrono::steady_clock::now();
size_t frames = 0;
for(;;) {
auto diff = std::chrono::steady_clock::now() - begin;
if (diff > std::chrono::seconds(1)) {
fprintf(stderr, "fps = %g\n", frames * 1000.0 / std::chrono::duration_cast(diff).count());
if (iter_count >= 15)
break;
begin = std::chrono::steady_clock::now();
frames = 0;
++iter_count;
}
queue.enqueueWriteBuffer(src, CL_FALSE, 0, 2560 * 1440 * 4, srcbuf.data());
func(cl::EnqueueArgs(queue, cl::NDRange(2560 / 2, 1440 / 2)), dst, src); // comment out this line and the 3D usage gone.
queue.enqueueReadBuffer(dst, CL_TRUE, 0, 2560 * 1440 * 1.5, dstbuf.data());
frames += 1;
}
return 0;
}
Моя среда — 64-разрядная версия Windows 10 с настольным компьютером RTX 2060; он использует 90% 3D. При этом он использует гораздо меньше (52%) iGPU Intel UHD 630 (i7-10700).
[img]https:// i.sstatic.net/e8HC3DPv.png[/img]
Это также произошло с настольной видеокартой RTX 2080 или настольной видеокартой Vega64.
Но этого не произошло с ноутбуком RTX 2080 или ноутбуком RTX 4090.
< blockquote>
edit: я обнаружил, что если я настрою в BIOS прямую связь монитора ноутбука с дискретной графической платой, он будет действовать так же, как настольный компьютер.
Я проверил пример кода от Nvidia ( https://developer.nvidia.com/opencl ), и он использует ту же пару API, что и я.
Когда RTX 2060 запускает код при высокой загрузке 3D-графического процессора, энергопотребление графического процессора низкое (при использовании nvidia-smi dmon), составляет 51 Вт. при запуске Furmark 2 с таким же использованием 3D-графического процессора используется 165 Вт.
Я не знаю, как объяснить этот феномен и с чего начать оптимизацию кода.
Я не знаю, как объяснить этот феномен и с чего начать оптимизацию кода.
Я не знаю, как объяснить этот феномен и с чего начать оптимизацию кода.
p>
Угадайте:
Не сообщает ли счетчик производительности драйвера графической платы ложные данные в ОС, включено «3D» факт «Копия»?
Что-то не так с моей программной средой, которая отключила DMA для графической платы. Я совершенно уверен, что при чтении/записи жесткого диска в режиме PIO вместо DMA происходит высокая загрузка ЦП.
2024/5/26 добавляется :
Я попробовал CUDA запустить функцию ядра с тем же размером блока памяти, он копирует входные данные на выходные в функции ядра и действует точно так же, как и OpenCL. Меня это смущает, потому что это слишком медленно.
Код
Недавно я начал изучать OpenCL и пытался с его помощью преобразовать видеокадр RGBA в NV12. Я заметил, что в диспетчере задач для такой легкой задачи отображается недопустимо высокий уровень использования 3D. , но не используется Copy/Copy1/Copy2. При попытке внесения изменений я обнаружил, что это продолжает происходить даже при пустой функции ядра. [code]#define CL_HPP_ENABLE_EXCEPTIONS #define CL_HPP_TARGET_OPENCL_VERSION 200
#include #include #include #include #include
int main() { std::vector platdevlist; std::vector platforms; cl::Platform::get(&platforms); for (auto& p : platforms) { std::string platver = p.getInfo(); if (platver.find("OpenCL 2.") != std::string::npos || platver.find("OpenCL 3.") != std::string::npos) { cl::vector devices; p.getDevices(CL_DEVICE_TYPE_ALL, &devices);
for (auto& d : devices) { platdevlist.emplace_back(std::make_pair(p, d)); } } }
for(int i = 0; i < platdevlist.size(); ++i) { fprintf(stderr, "%d: platform: %s, device: %s\n", i, platdevlist[i].first.getInfo().c_str(), platdevlist[i].second.getInfo().c_str() ); } int selected_index; fprintf(stderr, "select one: \n"); scanf("%d", &selected_index);
auto selected = platdevlist[selected_index];
auto ctx = cl::Context(cl::vector{ selected.second }); auto queue = cl::CommandQueue{ ctx, selected.second, cl::QueueProperties::None };
std::string sourcecode{ "kernel void empty(global char* dst, global const char* src) { }" }; auto program = cl::Program(ctx, {sourcecode}); try { program.build("-cl-std=CL2.0"); } catch (...) { for (auto& pair : program.getBuildInfo()) { fprintf(stderr, "%s", pair.second.c_str()); }
auto iter_count = 1; auto begin = std::chrono::steady_clock::now(); size_t frames = 0; for(;;) { auto diff = std::chrono::steady_clock::now() - begin; if (diff > std::chrono::seconds(1)) { fprintf(stderr, "fps = %g\n", frames * 1000.0 / std::chrono::duration_cast(diff).count()); if (iter_count >= 15) break; begin = std::chrono::steady_clock::now(); frames = 0; ++iter_count; } queue.enqueueWriteBuffer(src, CL_FALSE, 0, 2560 * 1440 * 4, srcbuf.data()); func(cl::EnqueueArgs(queue, cl::NDRange(2560 / 2, 1440 / 2)), dst, src); // comment out this line and the 3D usage gone. queue.enqueueReadBuffer(dst, CL_TRUE, 0, 2560 * 1440 * 1.5, dstbuf.data()); frames += 1; } return 0; } [/code] Моя среда — 64-разрядная версия Windows 10 с настольным компьютером RTX 2060; он использует 90% 3D. При этом он использует гораздо меньше (52%) iGPU Intel UHD 630 (i7-10700). [img]https:// i.sstatic.net/e8HC3DPv.png[/img] [img]https://i.sstatic.net/HpNSw8Oy.png[/img]
Это также произошло с настольной видеокартой RTX 2080 или настольной видеокартой Vega64.
Но этого не произошло с ноутбуком RTX 2080 или ноутбуком RTX 4090. < blockquote> edit: я обнаружил, что если я настрою в BIOS прямую связь монитора ноутбука с дискретной графической платой, он будет действовать так же, как настольный компьютер.
Я проверил пример кода от Nvidia ( https://developer.nvidia.com/opencl ), и он использует ту же пару API, что и я. Когда RTX 2060 запускает код при высокой загрузке 3D-графического процессора, энергопотребление графического процессора низкое (при использовании nvidia-smi dmon), составляет 51 Вт. при запуске Furmark 2 с таким же использованием 3D-графического процессора используется 165 Вт. Я не знаю, как объяснить этот феномен и с чего начать оптимизацию кода. Я не знаю, как объяснить этот феномен и с чего начать оптимизацию кода. Я не знаю, как объяснить этот феномен и с чего начать оптимизацию кода. p> Угадайте: [list] [*]Не сообщает ли счетчик производительности драйвера графической платы ложные данные в ОС, включено «3D» факт «Копия»? [*]Что-то не так с моей программной средой, которая отключила DMA для графической платы. Я совершенно уверен, что при чтении/записи жесткого диска в режиме PIO вместо DMA происходит высокая загрузка ЦП. [/list] [b]2024/5/26 добавляется :[/b] Я попробовал CUDA запустить функцию ядра с тем же размером блока памяти, он копирует входные данные на выходные в функции ядра и действует точно так же, как и OpenCL. Меня это смущает, потому что это слишком медленно. Код [code]#include #include #include
static void HandleError( cudaError_t err, const char *file, int line ) { if (err != cudaSuccess) { printf( "%s in %s at line %d\n", cudaGetErrorString( err ), file, line ); exit( EXIT_FAILURE ); } } #define HANDLE_ERROR( err ) (HandleError( err, __FILE__, __LINE__ ))
__global__ void rgb2yuv( int width, int height, unsigned char* src, int srcstride, unsigned char* ybuf, int ystride, unsigned char* ubuf, int ustride, unsigned char* vbuf, int vstride ) { int xd2 = blockIdx.x; int yd2 = blockIdx.y; int x = xd2 * 2; int y = yd2 * 2;
Недавно я начал изучать OpenCL и пытался с его помощью преобразовать видеокадр RGBA в NV12.
Я заметил, что в диспетчере задач для такой легкой задачи отображается недопустимо высокий уровень использования 3D. , но не используется Copy/Copy1/Copy2....
Недавно я начал изучать OpenCL и пытался с его помощью преобразовать видеокадр RGBA в NV12.
Я заметил, что в диспетчере задач для такой легкой задачи отображается недопустимо высокий уровень использования 3D. , но не используется Copy/Copy1/Copy2....
Я пытаюсь заставить шейдер фрагментов GLSL искажать входящие фрагменты на основе их текстурных координат, чтобы плохо имитировать CRT.
После того, как код не заработал, я перенес его на C++, чтобы изменить значения RGB текстуры. Код работал так, как...
Недавно я много читал о программном обеспечении (в основном научном/математическом и шифровальном), которое переносит часть вычислений на графический процессор, что приводит к увеличению скорости поддерживаемых операций в 100–1000 (!) раз. >