2014-02-07 30 views
0

我有6000到6000,000的數據,並且這些數據必須發送到串行端口。我每3-5毫秒發送一次數據到串口。在發送數據之前,我必須對它進行一些計算(例如,對某些數據採用sin和cos),並在圖表上描繪數據。每次發送數據時,我都會在圖表上描述它,然後計算下一個數據,但是這方式有點慢(有時需要比3-5毫秒更多的時間)。動態或靜態描繪數據以加速發送數據

可以通過以下方式加快我的程序嗎?它們是正確的方式嗎?

1-首先計算運動圖表完全(例如 100sin(0.0001 *指數+ 10)對於x = 0〜500萬)和將其存儲在一個陣列 然後當我將數據發送到端口,我必須在數組 中找到數據,然後描繪併發送它。

2-如上所示,但將其存儲在文件中並從文件中讀取 。

想這是我的代碼:

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通過一個串口移動多達600萬個數據項?即使您的數據項只有1個字節,仍然需要至少1000 Mbs的串行比特率。這是什麼樣的串口?!? – RBarryYoung

+0

我每5毫秒發送22個字節到串行端口,每次我從圖表上的這22個字節添加一個點。我發送數據的時間是30-3000秒,所以我發送約30000/5到3000000/5數據。 – abdolahS

回答

0

好像你正在不必要地結合I/O綁定代碼和CPU綁定代碼。我會說更正確的方法是異步發送數據(並立即) - 異步和等待使這種令人難以置信的痛苦。當然,除非你想讓這兩個部分綁定,否則有一些原因。

此外,似乎你的問題可能會稍微複雜一些,因爲沒有辦法,一個簡單的罪或cos會花費你整整毫秒。你有沒有嘗試分析你的應用程序,找出真正的問題在哪裏?

例如,如果您在每個步驟中重新創建圖形並在某個用戶界面中顯示該圖形,則會出現大幅減速。做不是讓UI減慢你的底層溝通。相反,刷新UI應該只是偶爾進行一次,理想地與下面的數據流分開。

我覺得很難相信簡單的數學運算就足以讓你的代碼慢下來。我的電腦每毫秒可以輕鬆完成超過十萬次的罪惡行爲 - 如果你在繪製圖表時做了這麼多事情,那麼你正在做一些可怕的錯誤:D

+0

如果您的計算機可以在一毫秒內完成10百萬個SIN,那麼它比平均速度快得多。 SIN至少爲10 FLOP/100 OPs呼叫,所以這將是'10 FLOPs * 10 Million呼叫* 1000 ms/Sec = 100 GFLOPs'。這是我想要在我的桌面上使用的個人電腦! – RBarryYoung

+1

@RBarryYoung哎呀。看看誰在嘗試一個簡單的基準測試時忘記了優化:)我已經將值更改爲更真實,儘管它並沒有真正改變任何東西(除非你做了非常錯誤的事情,否則10萬次操作/秒仍然綽綽有餘)。當然,我的電腦可以輕鬆完成超過100個GFLOP,但只能在GPU上完成:D – Luaan

+0

是的,現在他已經清楚實際速率是多少,100K/sec就足夠了。 – RBarryYoung