隨著多核時代的到來,並行開發越來越展示出它的強大威力!使用並行程式,充分的利用系統資源,提高程式的效能。在.net 4.0中,微軟給我們提供了乙個新的命名空間:system.threading.tasks。這裡面有很多關於並行開發的東西,今天第一篇就介紹下最基礎,最簡單的——認識和使用parallel。
一、 parallel的使用
在parallel下面有三個常用的方法invoke,for和foreach。
1、parallel.invoke
這是最簡單,最簡潔的將序列的**並行化。
在這裡先講乙個知識點,就是stopwatch的使用,最近有一些人說找不到stopwatch,stopwatch到底是什麼東西,今天就來說明一下。
stopwatch在system.diagnostics命名控制項,要使用它就要先引用這個命名空間。
其使用方法如下:
下面進入整體,開始介紹parallel.invoke方法,廢話不多說了,首先新建乙個控制台程式,新增乙個類,**如下:12
3456
78910
1112
1314
1516
1718
1920
2122
2324
2526
2728
29public class paralleldemo
public void run2()
public void parallelinvokemethod()
}**很簡單,首先新加乙個類,在類中寫了兩個方法,run1和run2,分別等待一定時間,輸出一條資訊,然後寫了乙個測試方法parallelinvokemethod,分別用兩種方法呼叫run1和run2,然後在main方法中呼叫,下面來看一下執行時間如何:
大家應該能夠猜到,正常呼叫的話應該是5秒多,而parallel.invoke方法呼叫用了只有3秒,也就是耗時最長的那個方法,可以看出方法是並行執行的,執行效率提高了很多。
2、parallel.for
這個方法和for迴圈的功能相似,下面就在類中新增乙個方法來測試一下吧。**如下:12
3456
78910
1112
1314
1516
1718
1920
2122
2324
2526
2728
public void parallelformethod()
}stopwatch.stop();
console.writeline("normalfor run " + stopwatch.elapsedmilliseconds + " ms.");
stopwatch.reset();
stopwatch.start();
parallel.for(0, 10000, item =>
});stopwatch.stop();
console.writeline("parallelfor run " + stopwatch.elapsedmilliseconds + " ms.");
}寫了兩個迴圈,做了一些沒有意義的事情,目的主要是為了消耗cpu時間,同理在main方法中呼叫,執行結果如下圖:
可以看到,parallel.for所用的時間比單純的for快了1秒多,可見提公升的效能是非常可觀的。那麼,是不是parallel.for在任何時候都比for要快呢?答案當然是「不是」,要不然微軟還留著for幹嘛?
下面修改一下**,新增乙個全域性變數num,**如下:12
3456
78910
1112
1314
1516
1718
1920
2122
2324
2526
2728
2930
3132
3334
3536
37public void parallelformethod()
}stopwatch.stop();
console.writeline("normalfor run " + stopwatch.elapsedmilliseconds + " ms.");
stopwatch.reset();
stopwatch.start();
parallel.for(0, 10000, item =>
}});
stopwatch.stop();
console.writeline("parallelfor run " + stopwatch.elapsedmilliseconds + " ms.");
}parallel.for由於是並行執行的,所以會同時訪問全域性變數num,為了得到正確的結果,要使用lock,此時來看看執行結果:
是不是大吃一驚啊?parallel.for竟然用了15秒多,而for跟之前的差不多。這主要是由於並行同時訪問全域性變數,會出現資源爭奪,大多數時間消耗在了資源等待上面。
一直說並行,那麼從**可以看出來parallel.for是並行執行的呢?下面來寫個測試**:12
34parallel.for(0, 100, i =>
);從0輸出到99,執行後會發現輸出的順序不對,用for順序肯定是對的,並行同時執行,所以會出現輸出順序不同的情況。12
3456
listlist = new list();
list.add(0);
parallel.foreach(list, item =>
);二、 parallel中途退出迴圈和異常處理
1、當我們使用到parallel,必然是處理一些比較耗時的操作,當然也很耗cpu和記憶體,如果我們中途向停止,怎麼辦呢?
在序列**中我們break一下就搞定了,但是並行就不是這麼簡單了,不過沒關係,在並行迴圈的委託引數中提供了乙個parallelloopstate,
該例項提供了break和stop方法來幫我們實現。
break: 當然這個是通知平行計算盡快的退出迴圈,比如平行計算正在迭代100,那麼break後程式還會迭代所有小於100的。
stop:這個就不一樣了,比如正在迭代100突然遇到stop,那它啥也不管了,直接退出。
下面來寫一段**測試一下:12
3456
78910
1112
1314
1516
public void parallelbreak()
bag.add(i);
});stopwatch.stop();
console.writeline("bag count is " + bag.count + ", " + stopwatch.elapsedmilliseconds);
}這裡使用的是stop,當數量達到300個時,會立刻停止;可以看到結果"bag count is 300",如果用break,可能結果是300多個或者300個,大家可以測試一下。
2、異常處理
首先任務是平行計算的,處理過程中可能會產生n多的異常,那麼如何來獲取到這些異常呢?普通的exception並不能獲取到異常,然而為並行誕生的aggregateexcepation就可以獲取到一組異常。
這裡我們修改parallel.invoke的**,修改後**如下:12
3456
78910
1112
1314
1516
1718
1920
2122
2324
2526
2728
2930
3132
3334
3536
3738
3940
4142
4344
4546
4748
49public class paralleldemo
public void run2()
public void parallelinvokemethod()
catch (aggregateexception aex)
}stopwatch.stop();
console.writeline("parallel run " + stopwatch.elapsedmilliseconds + " ms.");
stopwatch.reset();
stopwatch.start();
trycatch(exception ex)
stopwatch.stop();
console.writeline("normal run " + stopwatch.elapsedmilliseconds + " ms.");}}
順序呼叫方法我把異常處理寫一起了,這樣只能捕獲run1的異常資訊,大家可以分開寫。捕獲aggregateexception 異常後,用foreach迴圈遍歷輸出異常資訊,可以看到兩個異常資訊都顯示了。
c 並行和多執行緒程式設計 認識Parallel
隨著多核時代的到來,並行開發越來越展示出它的強大威力!使用並行程式,充分的利用系統資源,提高程式的效能。在.net 4.0中,微軟給我們提供了乙個新的命名空間 system.threading.tasks。這裡面有很多關於並行開發的東西,今天第一篇就介紹下最基礎,最簡單的 認識和使用parallel...
C 並行和多執行緒程式設計四 Task高階
一 task的巢狀task中還可以再巢狀task,thread中能不能這樣做,我只能說我是沒這樣寫過。task中的巢狀,我感覺其實也可以分開來寫,不過巢狀起來會方便管理一點。task中的巢狀分為兩種,關聯巢狀和非關聯巢狀,就是說內層的task和外層的task是否有聯絡,下面我們編寫 先來看一下非關聯...
Python 並行程式設計 多執行緒
最近看了一下 python並行程式設計手冊 雖然這本書薄薄的,包含內容挺多,但是有很多地方講的不清楚,而且有一些bug出現,講道理不推薦看這本書,但是我也隨手翻完了,也寫著玩,總結一下python並行程式設計,順便寫一寫書裡有問題的地方。這本書的問題過多,不建議閱讀!尤其是mpi4py之後的內容。棄...