2014-02-07 2 views
0

6000-6000,000 사이의 데이터가 있으며이 데이터는 직렬 포트로 보내야합니다. 나는 3 ~ 5ms마다 시리얼 포트에 데이터를 보낸다. 데이터를 보내기 전에 (예를 들어 sin, cos 데이터를 취하는 등) 계산을해야하고 차트에 데이터를 묘사해야합니다. 데이터를 보내면 차트에 묘사 한 다음 다음 데이터를 계산하지만이 방법은 조금 느립니다 (때로는 3-5ms보다 더 많은 시간이 걸립니다).데이터를 동적으로 또는 정적으로 묘사하여 데이터 전송 속도를 높이십시오.

다음과 같은 방법으로 프로그램 속도를 향상시킬 수 있습니까? 적절한 방법입니까?

1- 제 완전히 이동도를 계산 (예 100sin (0.0001 * 지수 + 10) × = 5000000-0 용) 및 배열 에 저장 한 다음 I 포트로 데이터를 전송하고있을 때, 나는 배열 에있는 자료를 찾아내어 그것을 묘사하고 보내야 만한다.

위와 같지만 파일에 저장하고 파일에서 읽는 것.

namespace WPF_Toolkit_SpeedTest 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public ObservableCollection<ChartItem> Items { set; get; } 

     public MainWindow() 
     { 
      InitializeComponent(); 
     } 
     #region winmm.dll functions 
     int _counter = 0; 
     public delegate void TimerEventHandler(UInt32 id, UInt32 msg, ref UInt32 userCtx, UInt32 rsv1, UInt32 rsv2); 

     /// <summary> 
     /// A multi media timer with millisecond precision 
     /// </summary> 
     /// <param name="msDelay">One event every msDelay milliseconds</param> 
     /// <param name="msResolution">Timer precision indication (lower value is more precise but resource unfriendly)</param> 
     /// <param name="handler">delegate to start</param> 
     /// <param name="userCtx">callBack data </param> 
     /// <param name="eventType">one event or multiple events</param> 
     /// <remarks>Dont forget to call timeKillEvent!</remarks> 
     /// <returns>0 on failure or any other value as a timer id to use for timeKillEvent</returns> 
     [DllImport("winmm.dll", SetLastError = true, EntryPoint = "timeSetEvent")] 
     static extern UInt32 timeSetEvent(UInt32 msDelay, UInt32 msResolution, TimerEventHandler handler, ref UInt32 userCtx, UInt32 eventType); 

     /// <summary> 
     /// The multi media timer stop function 
     /// </summary> 
     /// <param name="uTimerID">timer id from timeSetEvent</param> 
     /// <remarks>This function stops the timer</remarks> 
     [DllImport("winmm.dll", SetLastError = true)] 
     static extern void timeKillEvent(UInt32 uTimerID); 

     TimerEventHandler tim;//TimerEventHandler tim = new TimerEventHandler(this.Link); 
     public void Link(UInt32 id, UInt32 msg, ref UInt32 userCtx, UInt32 rsv1, UInt32 rsv2) 
     { 
      _counter++; 
      if ((_counter % 5) == 0) //if ((_counter % 10) == 0) 
      { 
       Dispatcher.Invoke(new Action(()=>{ 
        Items.Add(new ChartItem(_counter, 100*Math.Sin((.0002*_counter)))); 
        if (_counter>1000) 
        { 
         Items.RemoveAt(0); 
        } 
       })); 
      } 

      if (_counter > 10000) 
      { 
       timeKillEvent(id); 
       Dispatcher.Invoke(new Action(() => { button1.Content = stp.ElapsedMilliseconds; })); 
      } 
     } 
     uint timerId; 
     #endregion 

     private void button1_Click(object sender, RoutedEventArgs e) 
     { 

      Items = new ObservableCollection<ChartItem>(); 
      lineChart.ItemsSource = Items; 

      Items.Add(new ChartItem(0, 0)); 
      tim = new TimerEventHandler(this.Link); 
      uint rsv = 0; 
      stp.Start(); 
      button1.Content = stp.ElapsedMilliseconds; 
      timerId = timeSetEvent(1, 1, tim, ref rsv, 1); 
     } 
     System.Diagnostics.Stopwatch stp = new System.Diagnostics.Stopwatch(); 
    } 
    public class ChartItem : INotifyPropertyChanged 
    { 
     public ChartItem(double t, double v) 
     { 
      time = t; 
      myVar = v; 
     } 

     private double time; 

     public double Time 
     { 
      get { return time; } 
      set 
      { 
       time = value; 
       OnPropertyChanged("Time"); 
      } 
     } 

     private double myVar; 

     public double Value 
     { 
      get { return myVar; } 
      set 
      { 
       myVar = value; 
       OnPropertyChanged("Value"); 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 

     protected virtual void OnPropertyChanged(string propertyName) 
     { 
      if (this.PropertyChanged != null) 
      { 
       this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
    } 
} 

이 코드 만 묘사하는 부분을 표시하지만 같은 시간에 나는 또한 데이터를 전송 :

이 내 코드 가정하자.

+0

차트에서 매번 묘사하는 경우 그것이 천천히가는 원인이라고 생각합니다. 어쩌면 별도의 스레드로 값 비싼 작업을 배치하여 처리량을 높일 수도 있습니다. –

+0

3 ~ 5ms마다 직렬 포트를 통해 최대 6 백만 개의 데이터 항목을 이동한다는 말입니까? 데이터 항목이 1 바이트 일지라도 적어도 1000Mbs의 직렬 비트 전송률이 필요합니다. 어떤 종류의 직렬 포트가 이것입니까?!? – RBarryYoung

+0

직렬 포트에 매 5ms마다 22 바이트를 보내고 차트에이 22 바이트의 지점을 추가 할 때마다. 내가 데이터를 보내는 시간은 30-3000 초이므로 약 30000/5에서 3000000/5 데이터를 보냅니다. – abdolahS

답변

0

불필요하게 I/O 바운드 코드와 CPU 바운드 코드를 결합하는 것처럼 보입니다. 나는 비동기 적으로 (그리고 즉각적으로) 데이터를 보내는 것이 더 적절한 접근법이라고 말할 수있다 - 비동기식이고 기다리는 것은 믿을 수 없을만큼 고통 스럽다. 물론 두 부분을 묶고 싶은 이유가없는 한.

또한 단순한 죄 또는 cos이 전체 밀리 초를 차지할 방법이 없으므로 문제가 약간 더 복잡해 보입니다. 실제 문제가있는 곳을 찾기 위해 애플리케이션을 프로파일 링 해 보았습니까?

예를 들어 모든 단계에서 그래프를 다시 만들고 일부 UI에서 그래프를 표시하는 경우 엄청난 속도 저하가 발생합니다. 이 아니라면 UI가 기본 통신을 느리게합니다. 대신 UI 새로 고침은 한 번만 수행해야하며 아래의 데이터 흐름과 이상적으로 분리해야합니다.

간단한 수학 연산으로 코드를 느리게 처리 할 수 ​​있다고 생각하는 것이 정말 어렵습니다. 내 컴퓨터는 매 밀리 초마다 수십만 건의 죄 조작을 쉽게 처리 할 수 ​​있습니다. 그래프를 작성하는 동안이 작업을 많이 수행하는 경우 끔찍한 일을 할 수 있습니다. D

+0

컴퓨터가 밀리 초 단위로 천만 건의 SIN 호출을 수행 할 수있는 경우 평균보다 훨씬 빠릅니다. SIN은 최소 10 * FLOP/100 OPs 통화이므로 10 FLOPs * 1000 만 통화 * 1000 ms/Sec = 100 GFLOPs가됩니다. 그게 내 바탕 화면에 갖고 싶은 PC 야! – RBarryYoung

+1

@RBarryYoung 죄송합니다.간단한 벤치 마크를 시도 할 때 잊어 버린 사람을 보아라. 나는 값을 좀더 현실적으로 바꿨다. 실제로 아무 것도 바뀌지는 않았지만 (매우 100 만 ops/초는 당신이 잘못한 것을하지 않으면 충분하다.). 물론 내 컴퓨터는 GPU에서만 100GFLOP 이상을 쉽게 수행 할 수 있습니다. D – Luaan

+0

예, 실제 속도가 100K/초인 것이 분명해졌습니다. – RBarryYoung

관련 문제