좋은 코어 상관 관계를 찾기 위해 서버에서 코어 간 대기 시간을 벤치마킹하고 있습니다.
두 스레드의 핵심 선호도를 서로 다른 CPU로 설정하고 스레드 간 메시지 대기 시간을 계산하려고 합니다. 메시지는 를 통해 전달됩니다 std::atomic
. 실행 시간은 다음과 같이 계산됩니다.https://github.com/fuatu/core-latency-atomic
할당을 통한 핵심 선호도(POSIX)
void set_affinity(long cpu_num) {
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(cpu_num, &cpuset);
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
}
런타임은 두 개의 스레드가 액세스하는 원자로 측정됩니다.
enum State
{
Preparing,
Ready,
Ping,
Pong,
Finish,
};
class Sync
{
public:
State wait_as_long_as(State wait_state)
{
State loaded_state = state.load();
while (loaded_state == wait_state)
loaded_state = state.load();
return loaded_state;
}
void wait_until(State expected_state)
{
while (state.load() != expected_state)
{
}
}
void set(State new_state, State expected_state)
{
//state.store(new_state);
state.compare_exchange_strong(expected_state, new_state);
}
private:
std::atomic<State> state{Preparing};
};
static void set_affinity(unsigned int cpu_num)
{
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(cpu_num, &cpuset);
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
}
struct LatencyBench
{
LatencyBench(long first_cpu_, long second_cpu_)
: first_cpu{first_cpu_}
, second_cpu{second_cpu_}
{
}
void operator()(nonius::chronometer meter) const
{
Sync sync;
set_affinity(first_cpu);
std::thread t([&] {
set_affinity(second_cpu);
sync.set(Ready,Preparing);
State state = sync.wait_as_long_as(Ready);
while (state != Finish)
{
//if (state == Ping)
sync.set(Pong,Ping);
state = sync.wait_as_long_as(Pong);
}
});
sync.wait_until(Ready);
// start timer
sync.set(Ping,Ready);
sync.wait_until(Pong);
// stop timer
sync.set(Finish,Pong);
t.join();
}
const long first_cpu;
const long second_cpu;
};
./a.out
런타임 시간은 스레드 통신 중에만 측정되며 시작 시간 이나 두 번째 스레드를 시작하는 시간은 포함되지 않습니다 .
측정된 대기 시간은 동일한 프로그램 내에서 반복된 실험에 대해 견고합니다. 낮잠을 자고 main
두 번째로 분석을 실행해도 대기 시간은 여전히 첫 번째 측정의 약 1나노초 내에 있습니다. 하지만 ./a.out
다시 실행하면 측정된 대기 시간이 약 40나노초 정도 변경될 수 있습니다. 이는 또한 최상의 대기 시간으로 코어 쌍을 변경할 수도 있습니다.
동일한 실행 파일을 두 번 실행할 때 이러한 무작위 대기 시간 변경 뒤에 무엇이 있을 수 있는지 알고 계십니까?
추가 세부 사항:numactl -m 0 -N 0 ./a.out
NUMA 노드 0 내의 코어 쌍을 사용 하고 집중해도 이러한 상황이 완화되지는 않습니다.
하위 NUMA 노드로 구성된 서버를 사용하고 하위 NUMA 노드 내에 남아 있어도 이 내용은 변경되지 않습니다. Xeon 및 EPYC 프로세서에는 지연 시간 변동성이 복제되었습니다.
main
두 번째 분석에서는 아마도 모든 것을 캐시할 것이기 때문에 이러한 여러 분석을 통해 이것이 캐싱 문제가 아니라는 것을 나타낼 수 있기를 바랍니다 main
.