2
0

thread_affinity.h 3.7 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 pinToCore(QThread *thread, int coreId) {
  12. if (!thread) {
  13. qWarning() << "ThreadAffinity: null thread";
  14. return false;
  15. }
  16. #ifdef __linux__
  17. pthread_t nativeThread =
  18. reinterpret_cast<pthread_t>(thread->currentThreadId());
  19. cpu_set_t cpuset;
  20. CPU_ZERO(&cpuset);
  21. CPU_SET(coreId, &cpuset);
  22. int result =
  23. pthread_setaffinity_np(nativeThread, sizeof(cpu_set_t), &cpuset);
  24. if (result == 0) {
  25. return true;
  26. } else {
  27. qWarning() << "ThreadAffinity: Failed to pin thread to core" << coreId
  28. << "error:" << result;
  29. return false;
  30. }
  31. #else
  32. return false;
  33. #endif
  34. }
  35. static bool pinCurrentThreadToCore(int coreId) {
  36. #ifdef __linux__
  37. cpu_set_t cpuset;
  38. CPU_ZERO(&cpuset);
  39. CPU_SET(coreId, &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(coreId);
  51. return false;
  52. #endif
  53. }
  54. static bool pinToCores(QThread *thread, const std::vector<int> &coreIds) {
  55. if (!thread || coreIds.empty()) {
  56. qWarning() << "ThreadAffinity: invalid parameters";
  57. return false;
  58. }
  59. #ifdef __linux__
  60. pthread_t nativeThread =
  61. reinterpret_cast<pthread_t>(thread->currentThreadId());
  62. cpu_set_t cpuset;
  63. CPU_ZERO(&cpuset);
  64. for (int coreId : coreIds) {
  65. CPU_SET(coreId, &cpuset);
  66. }
  67. int result =
  68. pthread_setaffinity_np(nativeThread, 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(coreIds);
  77. return false;
  78. #endif
  79. }
  80. static int getCoreCount() {
  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> getCurrentAffinity() {
  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 resetAffinity(QThread *thread) {
  104. if (!thread) {
  105. return false;
  106. }
  107. #ifdef __linux__
  108. pthread_t nativeThread =
  109. reinterpret_cast<pthread_t>(thread->currentThreadId());
  110. cpu_set_t cpuset;
  111. CPU_ZERO(&cpuset);
  112. int coreCount = getCoreCount();
  113. for (int i = 0; i < coreCount; ++i) {
  114. CPU_SET(i, &cpuset);
  115. }
  116. int result =
  117. pthread_setaffinity_np(nativeThread, 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 renderCore{-1};
  126. int mainCore{-1};
  127. std::vector<int> workerCores;
  128. static AffinityStrategy autoDetect() {
  129. AffinityStrategy strategy;
  130. int coreCount = getCoreCount();
  131. if (coreCount >= 8) {
  132. strategy.mainCore = 0;
  133. strategy.renderCore = 1;
  134. strategy.workerCores = {2, 3};
  135. } else if (coreCount >= 4) {
  136. strategy.mainCore = 0;
  137. strategy.renderCore = 2;
  138. strategy.workerCores = {1, 3};
  139. } else {
  140. strategy.mainCore = -1;
  141. strategy.renderCore = -1;
  142. }
  143. return strategy;
  144. }
  145. };
  146. };
  147. } // namespace Render