我一直在研究Radix Sort的不同变体。起初我使用链接,这非常慢。然后我在使用val%(10 * pass)时使用了计数排序,并且最近将其转换为相应的字节并对它们进行排序,这使得我也可以按负值排序。
我想尝试使用多线程,并且只能在大约一半的时间内完成它。我想知道是否有人可以帮助查看我的代码,看看我在哪里遇到线程问题。我有每个线程计数每个字节排序。感谢:
public class radixSort {
public int[] array;
public int arraySize, arrayRange;
public radixSort (int[] array, int size, int range) {
this.array = array;
this.arraySize = size;
this.arrayRange = range;
}
public int[] RadixSort() {
Thread[] threads = new Thread[4];
for (int i=0;i<4;i++)
threads[i] = new Thread(new Radix(arraySize, i));
for (int i=0;i<4;i++)
threads[i].start();
for (int i=0;i<4;i++)
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
return array;
}
class Radix implements Runnable {
private int pass, size;
private int[] tempArray, freqArray;
public Radix(int size, int pass) {
this.pass = pass;
this.size = size;
this.tempArray = new int[size];
this.freqArray = new int[256];
}
public void run() {
int temp, i, j;
synchronized(array) {
for (i=0;i<size;i++) {
if (array[i] <= 0) temp = array[i] ^ 0x80000000;
else temp = array[i] ^ ((array[i] >> 31) | 0x80000000);
j = temp >> (pass << 3) & 0xFF;
freqArray[j]++;
}
for (i=1;i<256;i++)
freqArray[i] += freqArray[i-1];
for (i=size-1;i>=0;i--) {
if (array[i] <= 0) temp = array[i] ^ 0x80000000;
else temp = array[i] ^ ((array[i] >> 31) | 0x80000000);
j = temp >> (pass << 3) & 0xFF;
tempArray[--freqArray[j]] = array[i];
}
for (i=0;i<size;i++)
array[i] = tempArray[i];
}
}
}
}
答案 0 :(得分:2)
这种方法存在一个基本问题。要从多线程中获益,您需要为每个线程提供与其他线程相比不重叠的任务。通过synchonizing
array
,你已经做到了,所以一次只有一个线程可以正常工作,这意味着你得到线程的所有开销而没有任何好处。
考虑分区任务的方法,以便线程并行工作。例如,在第一次传递之后,具有1个高位的所有项目将在阵列的一个部分中,而具有零个高位的项目将在另一个部分中。您可以在阵列的每个部分上运行一个线程而不进行同步。
请注意,您的runnable
必须完全更改,以便它在数组的指定子集中执行一次传递,然后为下一次传递生成线程。
答案 1 :(得分:0)
除了错误的类和方法名称(类应该以大写字母开头,方法不应该),我可以看到你正在同步数组上的所有线程工作。所以它实际上根本不是平行的。
答案 2 :(得分:0)
我很确定你无法真正并行化RadixSort,至少在你尝试的方式上如此。有人指出你可以通过分而治之的方式来做到这一点,因为你首先按最高位排序,但事实上,RadixSort首先通过比较低位来工作,所以你不能真正分而治之。每次通过后,阵列基本上可以完全置换。
伙计们,证明我错了,但我认为像你想的那样并行化这个算法是不可能的。也许你可以并行化每次传递内部完成的(计数)排序,但要注意++不是原子操作。