तो मूल रूप से मुझे आज कोड के इस टुकड़े को अनुकूलित करने की आवश्यकता है। यह सबसे लंबे समय तक अनुक्रम पहले मिलियन प्रारंभिक संख्या के लिए कुछ समारोह द्वारा उत्पादित खोजने की कोशिश करता:क्या मल्टीथ्रेड गणना को न्यायसंगत बनाने वाला कोई "थ्रेसहोल्ड" है?
void doSearch() throws ExecutionException, InterruptedException {
final int numProc = Runtime.getRuntime().availableProcessors();
System.out.println("numProc = " + numProc);
ExecutorService executor = Executors.newFixedThreadPool(numProc);
long currTime = System.currentTimeMillis();
List<Future<ValueBean>> list = new ArrayList<Future<ValueBean>>();
for (int j = 2; j <= 1000000; j++) {
MyCallable<ValueBean> worker = new MyCallable<ValueBean>();
worker.setBean(new ValueBean(j, 0));
Future<ValueBean> f = executor.submit(worker);
list.add(f);
}
System.out.println(System.currentTimeMillis() - currTime);
int mostLen = 0;
int mostInt = 0;
for (Future<ValueBean> f : list) {
final int len = f.get().getLen();
if (len > mostLen) {
mostLen = len;
mostInt = f.get().getNum();
}
}
executor.shutdown();
System.out.println(System.currentTimeMillis() - currTime);
System.out.println("Most len is " + mostLen + " for " + mostInt);
}
public class MyCallable<T> implements Callable<ValueBean> {
public ValueBean bean;
public void setBean(ValueBean bean) {
this.bean = bean;
}
public ValueBean call() throws Exception {
long i = bean.getNum();
int len = 0;
while ((i = next(i)) != 1) {
len++;
}
return new ValueBean(bean.getNum(), len);
}
}
public class ValueBean {
int num;
int len;
public ValueBean(int num, int len) {
this.num = num;
this.len = len;
}
public int getNum() {
return num;
}
public int getLen() {
return len;
}
}
long next(long i) {
if (i % 2 == 0) {
return i/2;
} else {
return i * 3 + 1;
}
}
दुर्भाग्य से, बहु संस्करण में काम किया 5 बार धीमी:
public static void main(String[] args) {
int mostLen = 0;
int mostInt = 0;
long currTime = System.currentTimeMillis();
for(int j=2; j<=1000000; j++) {
long i = j;
int len = 0;
while((i=next(i)) != 1) {
len++;
}
if(len > mostLen) {
mostLen = len;
mostInt = j;
}
}
System.out.println(System.currentTimeMillis() - currTime);
System.out.println("Most len is " + mostLen + " for " + mostInt);
}
static long next(long i) {
if(i%2==0) {
return i/2;
} else {
return i*3+1;
}
}
मेरे गलती शुरू करने की कोशिश करने के लिए बहु सूत्रण था 4 प्रोसेसर (कोर) पर सिंगल-थ्रेडेड की तुलना में।
तब मैं थोड़ा और कच्चे दृष्टिकोण की कोशिश की:
static int mostLen = 0;
static int mostInt = 0;
synchronized static void updateIfMore(int len, int intgr) {
if (len > mostLen) {
mostLen = len;
mostInt = intgr;
}
}
public static void main(String[] args) throws InterruptedException {
long currTime = System.currentTimeMillis();
final int numProc = Runtime.getRuntime().availableProcessors();
System.out.println("numProc = " + numProc);
ExecutorService executor = Executors.newFixedThreadPool(numProc);
for (int i = 2; i <= 1000000; i++) {
final int j = i;
executor.execute(new Runnable() {
public void run() {
long l = j;
int len = 0;
while ((l = next(l)) != 1) {
len++;
}
updateIfMore(len, j);
}
});
}
executor.shutdown();
executor.awaitTermination(30, TimeUnit.SECONDS);
System.out.println(System.currentTimeMillis() - currTime);
System.out.println("Most len is " + mostLen + " for " + mostInt);
}
static long next(long i) {
if (i % 2 == 0) {
return i/2;
} else {
return i * 3 + 1;
}
}
और यह बहुत तेजी से काम किया, लेकिन अभी भी यह एकल थ्रेड दृष्टिकोण की तुलना में धीमी थी।
मुझे आशा है कि ऐसा इसलिए नहीं है क्योंकि मैंने बहुप्रतिष्ठक करने के तरीके को खराब कर दिया है, बल्कि यह विशेष गणना/एल्गोरिदम समानांतर गणना के लिए उपयुक्त नहीं है। अगर मैं गणना बदलने के लिए इसे और अधिक प्रोसेसर के साथ विधि next
की जगह गहन बनाने के लिए:
long next(long i) {
Random r = new Random();
for(int j=0; j<10; j++) {
r.nextLong();
}
if (i % 2 == 0) {
return i/2;
} else {
return i * 3 + 1;
}
}
दोनों बहु संस्करणों में दो बार के रूप में एक 4 कोर मशीन पर singlethreaded संस्करण की तुलना में तेजी से और अधिक से अधिक निष्पादित करने के लिए शुरू करते हैं।
तो स्पष्ट रूप से कुछ सीमा है कि आप अगर यह बहु सूत्रण पेश करने के लायक है और मेरे सवाल यह है कि निर्धारित करने के लिए उपयोग कर सकते हैं वहाँ होना चाहिए:
क्या बुनियादी नियम तय करने में मदद मिलेगी कि यदि किसी विशेष गणना काफी गहन है इसे समानांतर में चलाने के द्वारा अनुकूलित किया जा सकता है (वास्तव में इसे लागू करने के प्रयास किए बिना प्रयास?)
यह केवल प्रश्न से संबंधित है, लेकिन सवाल में एल्गोरिदम [कोलात्ज़ अनुमान] (http://en.wikipedia.org/wiki/Collatz_conjecture) से संबंधित है। यह geekdom धन्यवाद [यह] (http://xkcd.com/710/) और [यह] (http://store.xkcd.com/xkcd/#CollatzConjecture) में अधिक प्रसिद्ध है। –
मैं * अत्यधिक * ब्रायन गोएट्ज़ द्वारा पुस्तक [जावा कंसुरेंसी इन प्रैक्टिस] (http://www.amazon.com/Java-Concurrency- अभ्यास- Brian-Goetz/dp/0321349601) की अनुशंसा करता हूं। –