New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use usleep() instead of sched_yield() to yield cpu #13183
Conversation
but the module thread is yielding, so won't it let the lower priority thread get the CPU? |
@DvirDukhan @MeirShpilraien i remember some discussion about Redis Search around this topic. |
@oranagra from the document, if the module thread and the main thread do not use the same cpu, the module thread will always be the highest priority thread, and sched_yield() will always be the NOP.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok. approved.
i'd still like to get a reassurance from the search team if possible
Suggest using nanosleep instead of usleep.
|
@sundb Don't know the surrounding code, so just looking at the change. Are you expecting
https://pubs.opengroup.org/onlinepubs/7908799/xsh/usleep.html |
@tezc haha, there has always been ambiguity about whether or not to use usleep(0) to yield cpu, but it does get used a lot. |
@lipzhu thanks for figue out. |
@sundb I think that behavior is not guaranteed with |
@tezc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC we also saw the same thing on RediSearch once and also changed to usleep.
@MeirShpilraien i remember an issue with RM_Yield and trying to give up the GIL. calling usleep separately wouldn't have helped (unless maybe you released the mutex before?) |
@oranagra I am not talking about RM_Yield, I am talking about some other case where we use |
i see there was a combination of both usleep and yield. |
We saw that if we call |
ok, in our case we have |
this is a test to verify sched_yield() and usleep() when the main thread and thread bindings are on different CPU. #define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <unistd.h>
pthread_mutex_t mutex;
int thread_got_lock = 0;
int complexCalculation(void) {
volatile int result = 0;
for (int i = 0; i < 10000000; ++i) {
result += i;
}
return result;
}
void *thread_func(void *arg) {
pthread_mutex_lock(&mutex);
thread_got_lock = 1;
while (1) {
complexCalculation();
pthread_mutex_unlock(&mutex);
sched_yield();
// usleep(0);
pthread_mutex_lock(&mutex);
}
return NULL;
}
int main() {
int cpu_main = 0; /* bind cup 0 for main thread */
int cpu_thread = 31; /* bind cup 31 for thread */
/* set the cpu affinity of the main thread to 0 */
cpu_set_t cpuset_main;
CPU_ZERO(&cpuset_main);
CPU_SET(cpu_main, &cpuset_main);
if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset_main) != 0) {
fprintf(stderr, "Error setting main thread affinity\n");
return 1;
}
pthread_t thread;
if (pthread_create(&thread, NULL, thread_func, NULL) != 0) {
fprintf(stderr, "Error creating thread\n");
return 1;
}
/* set the cpu affinity of the thread to 31 */
cpu_set_t cpuset_thread;
CPU_ZERO(&cpuset_thread);
CPU_SET(cpu_thread, &cpuset_thread);
if (pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset_thread) != 0) {
fprintf(stderr, "Error setting thread affinity\n");
return 1;
}
while (!thread_got_lock) {
usleep(0);
}
printf("thread has acquired the lock\n");
pthread_mutex_lock(&mutex);
return 0;
} |
what do you mean? that both |
in my tests sched_yield() doesn't let the main thread to get the lock, but usleep(0) does. |
ok, then merge away! |
@oranagra It's okay now. |
when the main thread and the module thread are in the same thread, sched_yield() can work well.
when they are both bind to different cpus, sched_yield() will look for the thread with the highest priority, and if the module thread is always the highest priority on a cpu, it will take a long time to let the main thread to reacquire the GIL.
ref https://man7.org/linux/man-pages/man2/sched_yield.2.html