thread_affinity.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #pragma once
  2. #include <QDebug>
  3. #include <QThread>
  4. #ifdef __linux__
  5. #include <pthread.h>
  6. #include <sched.h>
  7. #endif
  8. namespace Render {
  9. class ThreadAffinity {
  10. public:
  11. static bool pin_to_core(QThread *thread, int core_id) {
  12. if (!thread) {
  13. qWarning() << "ThreadAffinity: null thread";
  14. return false;
  15. }
  16. #ifdef __linux__
  17. pthread_t native_thread =
  18. reinterpret_cast<pthread_t>(thread->currentThreadId());
  19. cpu_set_t cpuset;
  20. CPU_ZERO(&cpuset);
  21. CPU_SET(core_id, &cpuset);
  22. int result =
  23. pthread_setaffinity_np(native_thread, sizeof(cpu_set_t), &cpuset);
  24. if (result == 0) {
  25. return true;
  26. } else {
  27. qWarning() << "ThreadAffinity: Failed to pin thread to core" << core_id
  28. << "error:" << result;
  29. return false;
  30. }
  31. #else
  32. return false;
  33. #endif
  34. }
  35. static bool pin_current_thread_to_core(int core_id) {
  36. #ifdef __linux__
  37. cpu_set_t cpuset;
  38. CPU_ZERO(&cpuset);
  39. CPU_SET(core_id, &cpuset);
  40. int result =
  41. pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
  42. if (result == 0) {
  43. return true;
  44. } else {
  45. qWarning() << "ThreadAffinity: Failed to pin current thread, error:"
  46. << result;
  47. return false;
  48. }
  49. #else
  50. Q_UNUSED(core_id);
  51. return false;
  52. #endif
  53. }
  54. static bool pin_to_cores(QThread *thread, const std::vector<int> &core_ids) {
  55. if (!thread || core_ids.empty()) {
  56. qWarning() << "ThreadAffinity: invalid parameters";
  57. return false;
  58. }
  59. #ifdef __linux__
  60. pthread_t native_thread =
  61. reinterpret_cast<pthread_t>(thread->currentThreadId());
  62. cpu_set_t cpuset;
  63. CPU_ZERO(&cpuset);
  64. for (int core_id : core_ids) {
  65. CPU_SET(core_id, &cpuset);
  66. }
  67. int result =
  68. pthread_setaffinity_np(native_thread, sizeof(cpu_set_t), &cpuset);
  69. if (result == 0) {
  70. return true;
  71. } else {
  72. qWarning() << "ThreadAffinity: Failed to pin thread, error:" << result;
  73. return false;
  74. }
  75. #else
  76. Q_UNUSED(core_ids);
  77. return false;
  78. #endif
  79. }
  80. static int get_core_count() {
  81. #ifdef __linux__
  82. return static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN));
  83. #else
  84. return QThread::idealThreadCount();
  85. #endif
  86. }
  87. static std::vector<int> get_current_affinity() {
  88. std::vector<int> cores;
  89. #ifdef __linux__
  90. cpu_set_t cpuset;
  91. CPU_ZERO(&cpuset);
  92. if (pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset) ==
  93. 0) {
  94. for (int i = 0; i < CPU_SETSIZE; ++i) {
  95. if (CPU_ISSET(i, &cpuset)) {
  96. cores.push_back(i);
  97. }
  98. }
  99. }
  100. #endif
  101. return cores;
  102. }
  103. static bool reset_affinity(QThread *thread) {
  104. if (!thread) {
  105. return false;
  106. }
  107. #ifdef __linux__
  108. pthread_t native_thread =
  109. reinterpret_cast<pthread_t>(thread->currentThreadId());
  110. cpu_set_t cpuset;
  111. CPU_ZERO(&cpuset);
  112. int core_count = get_core_count();
  113. for (int i = 0; i < core_count; ++i) {
  114. CPU_SET(i, &cpuset);
  115. }
  116. int result =
  117. pthread_setaffinity_np(native_thread, sizeof(cpu_set_t), &cpuset);
  118. return result == 0;
  119. #else
  120. Q_UNUSED(thread);
  121. return false;
  122. #endif
  123. }
  124. struct AffinityStrategy {
  125. int render_core{-1};
  126. int main_core{-1};
  127. std::vector<int> worker_cores;
  128. static AffinityStrategy auto_detect() {
  129. AffinityStrategy strategy;
  130. int core_count = get_core_count();
  131. if (core_count >= 8) {
  132. strategy.main_core = 0;
  133. strategy.render_core = 1;
  134. strategy.worker_cores = {2, 3};
  135. } else if (core_count >= 4) {
  136. strategy.main_core = 0;
  137. strategy.render_core = 2;
  138. strategy.worker_cores = {1, 3};
  139. } else {
  140. strategy.main_core = -1;
  141. strategy.render_core = -1;
  142. }
  143. return strategy;
  144. }
  145. };
  146. };
  147. } // namespace Render