Created
May 21, 2018 16:40
-
-
Save lamianlbe/8a8190365c4104ab80d70594e56a0236 to your computer and use it in GitHub Desktop.
Nvidia Linux graphic process limitation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cmake_minimum_required(VERSION 3.9) | |
project(NVLimit) | |
set(CMAKE_CXX_STANDARD 11) | |
link_libraries(EGL pthread X11) | |
add_executable(NVLimit main.cpp) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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