簡體   English   中英

C ++-如何提高此方法的執行速度

[英]C++ - how to improve this methods execution speed

我正在努力提高即將發布的作業的編程技巧,這涉及到解決問題,同時使其盡可能高效,快速地運行。 我知道這是一段相當有限的代碼,但是如果有什么話會使其運行得更快。

該方法采用一個數組,其中包含保存事務的詳細信息,用於維護循環的事務數為100。 因此獲取平均股數然后返回。 英語不太流利,所以希望這很有意義,謝謝

double Analyser::averageVolume()
{
    // Your code
    double averageNumShares = 0;
    for(int i = 0; i < nTransactions; i++)
    {
        averageNumShares += tArray[i].numShares;
    }
    averageNumShares = averageNumShares / nTransactions;
    return averageNumShares;
    //return 0
}

如果您需要計算n個數字的平均值,恐怕您無法將其加速超出示例代碼中線性時間方法的速度。

除非將其用作另一個更復雜的算法的一部分,否則您可以不必計算平均值或沿這些直線計算而逃脫,否則取平均值將是O(n)操作,該操作基本上涉及將所有求和數組中的元素,然后除以元素數。 正是您所擁有的。

為什么沒有該對象的其他兩個值-總計和項目數?

然后,計算平均值可以利用這些數字。 快速而簡單(可能是內聯函數!)。

這是另一種方法,類似於Ed Heal提出的方法,該方法應該對舍入錯誤不太敏感。 平均值的舍入誤差隨累加和的大小而增加。 這可能對您來說不是問題,但這是需要注意的。

這是一個使平均舍入誤差最小的迭代算法,這是我在Ross的舊版本(大約1998年)中首次遇到的:

double Analyser::averageVolume()
{
  double averageNumShares = 0.0;

  for (int i = 0; i < nTransactions; i++)
  {
    double delta = (tArray[i].numShares - averageNumShares) / (i+1);
    averageNumShares += delta;
  }

  return averageNumShares;
}

這通過推導平均值的遞歸定義而起作用。 也就是說,給定樣本x[1] ,..., x[j] ,..., x[N] ,您可以根據樣本x[M+1]和樣本x[M+1]計算前M+1樣本的平均值。前M樣本的平均值:

sum(M) = x[1] + x[2] + ... + x[M]
thus avg(M+1) = sum(M+1)/(M+1) and avg(M) = sum(M)/M

avg(M+1) - avg(M) = sum(M+1)/(M+1) - sum(M)/M
    = [ M*sum(M+1) - (M+1)*sum(M) ]/[ M * (M+1) ]
    = [ M*(x[M+1] + sum(M)) - M*sum(M) - sum(M) ] / [ M*(M+1) ]
    = [ M*x[M+1] - sum(M) ] / [ M*(M+1) ]
    = [ x[M+1] - avg(M) ] / (M+1)
thus: avg(M+1) = avg(M) + [ x[M+1] - avg(M) ]/(M+1)

為了了解兩種方法的舍入誤差,請嘗試計算10 ^ 7個樣本的平均值,每個樣本等於1035.41。 您的原始方法(在我的硬件上)平均返回1035.40999988683。 上面的迭代方法返回的精確平均值為1035.41。

不幸的是,兩者在某個時候都是O(N)。 您原來的方案有N個加法和一個除法。 迭代方案具有N個加,減和除法,因此您需要付出更多的准確性。

如果使用gcc,請更改優化級別。

簡短的答案:就速度而言,此代碼是最好的。 您可以調整的是如何編譯它。 或者很明顯,如果可以的話,可以在匯編中重寫它。

“被拉伸”的答案:現在...如果您真的想嘗試獲得更好的性能,已經嘗試使用所有可用的編譯器優化標志和優化,並且已經准備好以可能更高的速度犧牲代碼的可讀性,則可以考慮重寫:

for(int i = 0; i < nTransactions; i++)
    {
        averageNumShares += tArray[i].numShares;
    }

pointerValue = &(tArray[0].numShares);
pointerIncrement = sizeof(tArray[0]);
for(int i = 0; i < nTransactions; i++)
    {
        averageNumShares += *(pointerValue++pointerIncrement);
    }

通過向您展示編譯器所做的全部工作是在每次循環迭代時跳過固定偏移量,可能會獲得更好的性能。 一個好的編譯器應該能夠在您的初始代碼中看到它。 而新代碼可能會使您的性能下降。 這實際上取決於您的編譯器的細節,我不建議您采用這種方法,除非您迫切希望獲得比編譯器所提供的性能更好的性能,並且不想跳到使用內聯匯編或內在函數(如果任何可用的)。

int i= nTransactions;
while(i--){// test for 0 is faster
    averageNumShares += (q++)->numShares;// increment pointer is faster than offset
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM