Я пытаюсь изменить код, чтобы он мог работать с многопоточностью.Я наткнулся на потерю производительности при установке Runnable вокруг некоторого кода .
Для пояснения: оригинальный код, назовем его
//doSomething
, получил Runnable вокруг неговот так:
Runnable r = new Runnable()
{
public void run()
{
//doSomething
}
}
Затем я отправляю исполняемый файл в ChachedThreadPool ExecutorService.Это мой первый шаг к многопоточности этого кода, чтобы увидеть, работает ли код с одним потоком так же быстро, как и исходный код.
Однако это не так.Когда // doSomething выполняется примерно за 2 секунды, Runnable выполняется примерно за 2,5 секунды. Я должен отметить, что некоторый другой код, скажем, // doSomethingElse внутри Runnable не имел потери производительности по сравнению с исходным // doSomethingElse ,
Я предполагаю, что // doSomething имеет некоторые операции, которые не так быстры при работе в потоке, но я не знаю, что это может быть или что, вэтот аспект отличается от // doSomethingElse .
Может ли это быть использование final int [] / float [] массивов, что делает Runnable намного медленнее?Код // doSomethingElse также использовал некоторые финалы, но // doSomething использует больше.Это единственное, о чем я мог подумать.
К сожалению, код // doSomething довольно длинный и вне контекста, но я все равно опубликую его здесь.Для тех, кто знает алгоритм сегментации среднего сдвига, это часть кода, где вычисляется вектор среднего сдвига для каждого пикселя.Цикл 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 медленнее, чем оригинал?
Спасибо.
Редактировать: Измеренное время равно внутри кода, поэтому исключая запуск потока.