[英]How long will this take to run and how can I speed it up
我正在運行一些代碼來測試Brownian Motion和發散性,我很好奇這段代碼將花費多長時間以及如何加快該過程。 我對java還是比較陌生,所以目前的代碼還比較基本。 我正在運行的參數是1000000 1000000。
public class BrownianMotion {
public static void main(String[] args) {
/**starts vars for program*/
int N = Integer.parseInt(args[0]);
int T = Integer.parseInt(args[1]);
double sqtotal = 0;
double r;
double avg;
/**number of trials loop*/
for (int count=0;count<T;count++) {
/**started here so that x & y reset at each trial*/
int x = 0;
int y = 0;
/**loop for steps*/
for (int steps=0;steps<N;steps++) {
r = Math.random();
if (r < 0.25) x--;
else if (r < 0.50) x++;
else if (r < 0.75) y--;
else if (r < 1.00) y++;
}
/**squared total distance after each trial*/
sqtotal = sqtotal + (x*x+y*y);
}
/**average of squared total*/
avg = sqtotal/T;
System.out.println(avg);
}
}
先謝謝您的幫助。
據我了解您的代碼,您可以並行運行每個試用版。 如果您的CPU有多個內核,它將相應地運行得更快。
(編輯已添加)
通常,我會將算法轉換為Callable,創建數十個 (每個維,每個狀態等),然后使用Executors.newFixedThreadPool()創建合理大小的線程池(例如,對於我可能是Intel i3筆記本電腦(4個線程)並調用invokeAll()。 此博客文章中的更多詳細信息
但是,在您的100,000的示例中,效果並不理想。 理想的方法是使用CompletionService在作業完成時重新提交。 這開始變得復雜。
一種更簡單但不那么有效的方法(但仍然更快)可能是
您將浪費一些時間等待所有操作完成,但是仍然應該有明顯的加速。 由於大多數處理器的內核數分別為2,4,8等,因此略有改進是使集合的冪為2(而不是10,這使數學運算變得容易)
為了確定該函數將運行多長時間,是找到函數的運行復雜度O(N ^ 2)。 我相信。
這應該是一個並行工作的實現:
public class BrownianMotionThread extends Thread
{
int i;
int T;
int N;
int numberOfProcessors;
double sqtotal;
BrownianMotionThread(int i, int T, int N, int numberOfProcessors)
{
this.i = i;
this.T = T;
this.N = N;
this.numberOfProcessors = numberOfProcessors;
}
public void run()
{
double r;
for (int count=i;count<T;count+= numberOfProcessors) {
/**started here so that x & y reset at each trial*/
int x = 0;
int y = 0;
/**loop for steps*/
for (int steps=0;steps<N;steps++) {
r = Math.random();
if (r < 0.25) x--;
else if (r < 0.50) x++;
else if (r < 0.75) y--;
else if (r < 1.00) y++;
}
/**squared total distance after each trial*/
sqtotal = sqtotal + (x*x+y*y);
}
}
}
public class BrownianMotion {
static double sqtotal;
public static void main(String[] args) {
/**starts vars for program*/
final int N = Integer.parseInt(args[0]);
final int T = Integer.parseInt(args[1]);
final int numberOfProcessors = Runtime.getRuntime().availableProcessors();
BrownianMotionThread[] threads = new BrownianMotionThread[numberOfProcessors];
double avg;
/**number of trials loop*/
for(int i = 0; i < numberOfProcessors; i++)
{
threads[i] = new BrownianMotionThread(i,T,N,numberOfProcessors);
threads[i].start();
}
for(int i = 0; i < numberOfProcessors; i++)
{
try
{
threads[i].join();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
for(int i = 0; i < numberOfProcessors; i++)
{
sqtotal += threads[i].sqtotal;
}
/**average of squared total*/
avg = sqtotal/T;
System.out.println(avg);
}
}
至少有三種方法可以使代碼運行更快,從更有效到最不有效:
降低算法的復雜度。 現在,您的算法具有O(N^2)
時間復雜度:這意味着完成處理所需的時間與輸入長度的平方成正比。 您可能需要重新訪問該算法以減少不必要的計算或對中間結果進行優化。
在算法中引入並行性。 您的算法目前被實現為按順序執行的一大段代碼; 也就是說(除非在硬件級別進行指令流水線化),否則每條指令只能在前一條指令完成后才能執行。 您可以重寫代碼以使用線程在多個處理器之間分配工作,也可以使用並行化框架為您完成大部分工作。 這比第1點的效率低。因為機器中的處理器數量是恆定的,所以當您輸入給算法的輸入大小增加時,它就不會縮放。
使用更快的機器。 如果沒有以其他方式改進算法,那么加速它的唯一方法就是更快地運行它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.