我試圖改變一些代碼,所以它可以使用多線程。當圍繞代碼放置一個Runnable時,我偶然發現了一個性能損失。線程內部的代碼比外部線程慢?
對於澄清:原代碼,讓我們把它
//doSomething
了一個Runnable圍繞這樣的:
Runnable r = new Runnable()
{
public void run()
{
//doSomething
}
}
然後我提交了可運行的ChachedThreadPool的ExecutorService。這是我對多線程代碼的第一步,以查看代碼是否像原始代碼一樣以一個線程運行。
但是,情況並非如此。在大約2秒內執行// doSomething,Runnable執行約2.5秒。 我需要一提的是一些其他的代碼,說:// doSomethingElse,裏面一個Runnable 沒有性能損失相比原來// doSomethingElse。
我的猜測是,// DoSomething的有一些操作在一個線程工作時不那麼快,但我不知道它可能還是什麼,在方面是區別//doSomethingElse。
難道是使用final int []/float []數組使Runnable慢得多嗎? // doSomethingElse代碼也使用了一些決賽,但// doSomething使用更多。這是我能想到的唯一的事情。
不幸的是,代碼很長且不在上下文中,但我會在這裏發佈它。對於那些知道Mean Shift分段算法的人來說,這是代表每個像素正在計算均值漂移向量的代碼的一部分。通過每個像素中的for循環
for(int i=0; i<L; i++)
運行。
timer.start(); // this is where I start the timer
// Initialize mode table used for basin of attraction
char[] modeTable = new char [L]; // (L is a class property and is about 100,000)
Arrays.fill(modeTable, (char)0);
int[] pointList = new int [L];
// Allcocate memory for yk (current vector)
double[] yk = new double [lN]; // (lN is a final int, defined earlier)
// Allocate memory for Mh (mean shift vector)
double[] Mh = new double [lN];
int idxs2 = 0; int idxd2 = 0;
for (int i = 0; i < L; i++) {
// if a mode was already assigned to this data point
// then skip this point, otherwise proceed to
// find its mode by applying mean shift...
if (modeTable[i] == 1) {
continue;
}
// initialize point list...
int pointCount = 0;
// Assign window center (window centers are
// initialized by createLattice to be the point
// data[i])
idxs2 = i*lN;
for (int j=0; j<lN; j++)
yk[j] = sdata[idxs2+j]; // (sdata is an earlier defined final float[] of about 100,000 items)
// Calculate the mean shift vector using the lattice
/*****************************************************/
// Initialize mean shift vector
for (int j = 0; j < lN; j++) {
Mh[j] = 0;
}
double wsuml = 0;
double weight;
// find bucket of yk
int cBucket1 = (int) yk[0] + 1;
int cBucket2 = (int) yk[1] + 1;
int cBucket3 = (int) (yk[2] - sMinsFinal) + 1;
int cBucket = cBucket1 + nBuck1*(cBucket2 + nBuck2*cBucket3);
for (int j=0; j<27; j++) {
idxd2 = buckets[cBucket+bucNeigh[j]]; // (buckets is a final int[] of about 75,000 items)
// list parse, crt point is cHeadList
while (idxd2>=0) {
idxs2 = lN*idxd2;
// determine if inside search window
double el = sdata[idxs2+0]-yk[0];
double diff = el*el;
el = sdata[idxs2+1]-yk[1];
diff += el*el;
//...
idxd2 = slist[idxd2]; // (slist is a final int[] of about 100,000 items)
}
}
//...
}
timer.end(); // this is where I stop the timer.
有更多的代碼,但最後while循環是我第一次注意到,在性能上的差異。
任何人都可以想到爲什麼這段代碼在Runnable內運行得比原來慢嗎?
謝謝。
編輯:測量的時間是內部的代碼,所以不含啓動的線程的。
如果你拿一些運行260ms的東西,把它包裝在一個Runnable中,並且只運行一次,那麼是的,由於線程的啓動開銷會花費更長的時間。一次運行一些東西並不是一個很好的線程使用。請解釋你爲什麼要運行這個多線程。 – 2010-11-15 14:34:51
我提到其他代碼在Runnable內部和在外部一樣快。但是的確,總的運行時間比那個長。此代碼完成後,Runnable內部需要約3.5秒,而外部則需要2秒。我想以多線程的形式運行這個代碼,作爲應該實現的實時應用程序的一部分。巨大的for-loop(從0到L)可以分成幾部分。 – RemiX 2010-11-15 14:43:21
根據您的編輯,並行代碼(和測試)的外觀如何? – gustafc 2010-11-15 14:55:55