Skip to content

Instantly share code, notes, and snippets.

@lamianlbe
Created May 21, 2018 16:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lamianlbe/8a8190365c4104ab80d70594e56a0236 to your computer and use it in GitHub Desktop.
Save lamianlbe/8a8190365c4104ab80d70594e56a0236 to your computer and use it in GitHub Desktop.
Nvidia Linux graphic process limitation
Dependencies:
sudo apt install libx11-dev
Compile:
Use cmake, or
g++ -o NVLimit main.cpp -std=c++11 -lEGL -lpthread -lX11
Run:
Make sure Xorg is running and NV Linux driver is correctly configured
./NVLimit
Test:
Tested on Ubuntu 16.04, NVidia Driver 384.90, Quadro P2000 / Tesla P4 / Tesla P100
cmake_minimum_required(VERSION 3.9)
project(NVLimit)
set(CMAKE_CXX_STANDARD 11)
link_libraries(EGL pthread X11)
add_executable(NVLimit main.cpp)
#include <stdio.h>
#include <unistd.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <signal.h>
#include <vector>
static PFNEGLDEBUGMESSAGECONTROLKHRPROC eglDebugMessageControlKHR = nullptr;
static int EGL_CONFIG_ATTRS[] = {
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_STENCIL_SIZE, 0,
EGL_DEPTH_SIZE, 0,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};
static int EGL_CONTEXT_ATTRS[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
static void eglDebugCallback(EGLenum error, const char *command, EGLint messageType, EGLLabelKHR threadLabel, EGLLabelKHR objectLabel, const char* message) {
fprintf(stderr, "%p %s %s\n", (void *)error, command, message);
}
static void testEGL(int i, int fd) {
EGLDisplay display;
EGLContext context;
EGLConfig config;
eglDebugMessageControlKHR = reinterpret_cast<PFNEGLDEBUGMESSAGECONTROLKHRPROC>(eglGetProcAddress("eglDebugMessageControlKHR"));
EGLAttrib attribs[] = {EGL_DEBUG_MSG_CRITICAL_KHR, EGL_TRUE, EGL_DEBUG_MSG_ERROR_KHR, EGL_TRUE, EGL_DEBUG_MSG_WARN_KHR, EGL_TRUE, EGL_DEBUG_MSG_INFO_KHR, EGL_TRUE, EGL_NONE};
eglDebugMessageControlKHR(eglDebugCallback, attribs);
Display *x11 = XOpenDisplay(":0");
if (x11 == nullptr) {
fprintf(stderr, "Failed to connect to XOrg at :0\n");
char output = 1;
write(fd, &output, sizeof(output));
return;
}
display = eglGetDisplay(x11);
eglInitialize(display, nullptr, nullptr);
int configCount = 1;
eglChooseConfig(display, EGL_CONFIG_ATTRS, &config, 1, &configCount);
eglBindAPI(EGL_OPENGL_ES_API);
context = eglCreateContext(display, config, nullptr, EGL_CONTEXT_ATTRS);
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context);
char output;
if (eglGetError() == EGL_SUCCESS) {
fprintf(stderr, "Created EGLContext %d\n", i);
output = 0;
} else {
fprintf(stderr, "Failed to create EGLContext %d\n", i);
output = 1;
}
write(fd, &output, sizeof(output));
}
int main() {
std::vector<pid_t> children;
for (int i=0; i<256; i++) {
int fds[2] = {};
if (pipe(fds)) {
perror("failed to create pipe\n");
break;
}
pid_t pid = fork();
if (pid < 0) {
perror("failed to fork child process\n");
break;
} else if (pid == 0) {
close(fds[0]);
testEGL(i, fds[1]);
close(fds[1]);
while (true) {
sleep(UINT32_MAX);
}
} else {
children.push_back(pid);
close(fds[1]);
char buffer = 0;
read(fds[0], &buffer, sizeof(buffer));
close(fds[0]);
if (buffer != 0) {
break;
}
}
}
getchar();
for (pid_t pid : children) {
kill(pid, SIGKILL);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment