2016-11-09 8 views
0

1 루프에 대해 100 마이크로 초 주기로 루프해야하는 프로그램을 작성했습니다. 나는 to가 고정 된 시간에 정기적으로 반복되는 것을 발견했다. 그러나 루핑 시간이 너무 짧게 설정되면 문제가 발생합니다. C++은 "every"마다 100 microsecond의 작업을 일시 중지하지 않고 정확하게 수행합니다.

데모 코드 (완료되지 코드) 다음 인에 :

  1. 증가 count 매 100 마이크로 초.
  2. count을 1 초마다 표시합니다.

예상되는 결과는 매초 약 10000 개입니다.

그러나 의 결과는 약 4000 초를 나타냅니다..

void f2(int input) 
{ 
    auto start = std::chrono::system_clock::now(); 
    auto displayStart = std::chrono::system_clock::now(); 
    while(true){ //keep looping quickly 
     auto now = std::chrono::system_clock::now(); 
     auto interval = std::chrono::duration_cast<std::chrono::microseconds>(now - start); 
     if (interval.count() > input){ //if 100 microsecond do 
      count++; 
      start = std::chrono::system_clock::now(); 
     } 

     auto displayNow = std::chrono::system_clock::now(); 
     auto displayInterval = std::chrono::duration_cast<std::chrono::microseconds>(displayNow - displayStart); 
     if (displayInterval.count() > 1000000){ //if 1 second do 
     std::cout<< "1 second count: "<<count<<std::endl; 
     count=0; 
     displayStart = std::chrono::system_clock::now(); 

     } 

    } 

} 

후 나는 CPU 스케줄링이에 대한 문제가있을 수 있습니다 생각합니다. 프로그램이 모든 루프에서 정상적으로 작동하는지 확인했습니다. 각 반복에는 약 100 마이크로 초가 소요됩니다. 그러나 프로그램/스레드가 일시 중지되어 CPU 재 스케쥴링을 기다릴 때 문제가 발생할 수 있습니다.

예를 들어, 더 명확하게 설명하기 위해 값을 확대 할 수 있습니다. 스레드가 1 초 동안 일시 중지되었습니다. 일반적으로 10000 번 증가합니다. 하지만 이제 다음 반복을 위해> 100 마이크로 초를 확인하므로 ++를 카운트하고 1 초가 지나면 카운터가 재설정됩니다. 이 경우 카운트는 1에 대해서만 증가합니다.

다음 코드를 수정하여 초당 10000 count++을 마칠 수 있습니다. 하지만 문제는 10000 카운트가 1 초에 균등하게 분배되지 않는다는 것입니다. 이것은 테스트 용 데모 프로그램입니다. 실제로 내가 원하는 동작은 정확하게 100 마이크로 초마다 정확하게 동작하는 것입니다.. 하지만 스레드의 일시 중지로 인해, 나는 여전히 이것을 해결하기위한 해결책을 찾지 못했습니다.

void f2(int input) 
{ 
    auto start = std::chrono::system_clock::now(); 
    auto displayStart = std::chrono::system_clock::now(); 
    while(true){ //keep looping quickly 
     auto now = std::chrono::system_clock::now(); 
     auto interval = std::chrono::duration_cast<std::chrono::microseconds>(now - start); 
     if (interval.count() > input){ //if 100 microsecond do 
      for(int i=0;i<interval.count()/input;i++){ //modified part 
       count++; 
      } 
      start = std::chrono::system_clock::now(); 

     } 


     auto displayNow = std::chrono::system_clock::now(); 
     auto displayInterval = std::chrono::duration_cast<std::chrono::microseconds>(displayNow - displayStart); 
     if (displayInterval.count() > 1000000){ //if 1 second do 
     std::cout<< "1 second count: "<<count<<std::endl; 
     count=0; 
     displayStart = std::chrono::system_clock::now(); 


     } 


    } 


} 

다음과 같은 방법이 있습니까 : 예. 프로세스를 일시 중지하지 않습니다. CPU에 유지 (가능하지 않음) 데모 프로그램에서 카운팅 동작을 매 100 마이크로 초마다 작동하게하려면? N 충분히 그 일정 지연이 문제가되지 않습니다 큰 곳

, 당신에게

+12

이러한 정밀도를 위해서는 [실시간 운영 체제] (https://en.wikipedia.org/wiki/Real-time_operating_system)가 필요합니다. 범용 OS는이를 실현시키지 못합니다. 운전자가 언제든지 프로그램을 중단시킬 수 있습니다. 어쨌든 - 어떤 종류의 문제를 해결하려고합니까? 10,000 FPS의 성능이 필요합니까? –

+0

답변 해 주셔서 감사합니다. 나는 프로그램을 위해 리눅스를 사용해야한다. 나는 다른 목적을 위해 일부 데이터를 계산하기위한 카운터에 대해 100 마이크로 초마다 * 0.08을 필요로하는 소프트웨어 스위치를 작성하고있다. (모든 포트에 대한 컴퓨팅 혼잡 데이터) –

+0

데이터를 계산하는 다른 방법을 찾아야 할 것입니다. 실제로 시도 할 수없는 시도한 솔루션이 아니라 실제 해결하려는 문제를 설명하면 도움이 될 수 있습니다. 또한보십시오 : [XY 문제] (http://xyproblem.info/) –

답변

0

유무 N 버킷 대단히 감사합니다.

쇠퇴 코드가 마지막으로 실행 된 시간을 기록하십시오.

새 패킷이 "나간다"는 경우, 쇠퇴 코드가 마지막으로 실행 된 시간 (100ms 미만, 버킷 0, 200ms, 버킷 1 등)에 따라 버킷에 넣습니다.

붕괴 코드가 실행되면 모든 것을 적절히 감쇠시킨 후 현재 값을 계산하고 타임 스탬프를 업데이트하십시오.

경합 (스레드 업데이트 및 스레드 감소)은 여전히 ​​문제가됩니다. 성능에 민감하지 않은 코드 (예 : 붕괴 코드)에서 카운터, 원자 플래그 및 포인터, 그리고 busy-loops의 이중 또는 삼중 버퍼링을 사용하여 어느 정도이를 수정할 수 있습니다.

또는 카운트를 기록하는 대신 타임 스탬프를 기록하십시오. 그 시점에서 붕괴를하면서 타임 스탬프의 버퍼를 소비한다. 비슷한 해결책으로 버퍼 크기와 다중 스레드와 관련된 비슷한 문제가 남아 있습니다.

또는 카운팅을 수행하는 코드에서 감쇠 계산을 수행하십시오.