Advertisement
Guest User

Untitled

a guest
May 19th, 2019
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.52 KB | None | 0 0
  1. # Async and Parallel Prgramming
  2.  
  3. ## 1- Understanding the Dangers of Concurrency
  4.  
  5. ### Race condition
  6.  
  7. A race condition exists when the outcome depends on the timing of events
  8.  
  9. ### Shared resources (Most common pitfall)
  10.  
  11. ```csharp
  12. int sum = 0;
  13. Task.Factory.StartNew(() => {
  14. sum = sum + obj1.Computation();
  15. })
  16. Task.Factory.StartNew(() => {
  17. sum = sum + obj2.Computation();
  18. })
  19. ```
  20.  
  21. ### Sequential to Parallel
  22.  
  23. ```csharp
  24. // Sequential
  25. private int SearchFiles(List<string> filenames, string pattern)
  26. {
  27. int hits = 0;
  28.  
  29. Regex re = new Regex(pattern, RegexOptions.Compiled | RegexOptions.Multipline);
  30.  
  31. foreach (string f in filenames)
  32. {
  33. byte[] bytes = File.ReadAllBytes(f);
  34.  
  35. string contents = System.Text.Encoding.UTF8.GetString(bytes);
  36.  
  37. Match m = re.Match(contents);
  38.  
  39. while(m.Success)
  40. {
  41. hits++;
  42. m = m.NextMatch();
  43. }
  44. }
  45.  
  46. return hits;
  47. }
  48.  
  49. // Parallel
  50. private int SearchFiles(List<string> filenames, string pattern)
  51. {
  52. int hits = 0;
  53.  
  54. Regex re = new Regex(pattern, RegexOptions.Compiled | RegexOptions.Multipline);
  55.  
  56. var tasks = new List<Task>();
  57.  
  58. foreach (string f in filenames)
  59. {
  60. var t = new Task.Factory.StartNew((arg) => {
  61. var fn = (string)arg;
  62.  
  63. byte[] bytes = File.ReadAllBytes(fn);
  64.  
  65. string contents = System.Text.Encoding.UTF8.GetString(bytes);
  66.  
  67. Match m = re.Match(contents);
  68.  
  69. while(m.Success)
  70. {
  71. hits++; // Shared Resource
  72. m = m.NextMatch();
  73. }
  74. });
  75.  
  76. tasks.Add(t);
  77. }
  78.  
  79. tasks.WaitAll(tasks.ToArray());
  80.  
  81. return hits;
  82. }
  83. ```
  84.  
  85. ### Solutions
  86.  
  87. - Redesign - To eliminate shared resources (eg. Each task uses only local storage)
  88. - Thread-safe - TPL offers thread-safe data structures (eg. ConcurrentDictionary)
  89. - Synchronization - To control access critical section (eg. Lock, Interlocked )
  90.  
  91. ### Solution 1 - Locking
  92.  
  93. ```csharp
  94. private int SearchFiles(List<string> filenames, string pattern)
  95. {
  96. int hits = 0;
  97.  
  98. Regex re = new Regex(pattern, RegexOptions.Compiled | RegexOptions.Multipline);
  99.  
  100. var tasks = new List<Task>();
  101. var l = new object();
  102.  
  103. foreach (string f in filenames)
  104. {
  105. var t = new Task.Factory.StartNew((arg) => {
  106. var fn = (string)arg;
  107.  
  108. byte[] bytes = File.ReadAllBytes(fn);
  109.  
  110. string contents = System.Text.Encoding.UTF8.GetString(bytes);
  111.  
  112. Match m = re.Match(contents);
  113.  
  114. while(m.Success)
  115. {
  116. lock (l)
  117. {
  118. hits++;
  119. }
  120. m = m.NextMatch();
  121. }
  122. });
  123.  
  124. tasks.Add(t);
  125. }
  126.  
  127. tasks.WaitAll(tasks.ToArray());
  128.  
  129. return hits;
  130. }
  131. ```
  132.  
  133. ### Solution 2 - InterLocking
  134.  
  135. ```csharp
  136. private int SearchFiles(List<string> filenames, string pattern)
  137. {
  138. int hits = 0;
  139.  
  140. Regex re = new Regex(pattern, RegexOptions.Compiled | RegexOptions.Multipline);
  141.  
  142. var tasks = new List<Task>();
  143.  
  144. foreach (string f in filenames)
  145. {
  146. var t = new Task.Factory.StartNew((arg) => {
  147. var fn = (string)arg;
  148.  
  149. byte[] bytes = File.ReadAllBytes(fn);
  150.  
  151. string contents = System.Text.Encoding.UTF8.GetString(bytes);
  152.  
  153. Match m = re.Match(contents);
  154.  
  155. while(m.Success)
  156. {
  157. System.Threading.Interlocked.Increment(ref hits);
  158. m = m.NextMatch();
  159. }
  160. });
  161.  
  162. tasks.Add(t);
  163. }
  164.  
  165. tasks.WaitAll(tasks.ToArray());
  166.  
  167. return hits;
  168. }
  169. ```
  170.  
  171. ### Solution 3 - Lock-free
  172.  
  173. ```csharp
  174. private int SearchFiles(List<string> filenames, string pattern)
  175. {
  176. int hits = 0;
  177.  
  178. Regex re = new Regex(pattern, RegexOptions.Compiled | RegexOptions.Multipline);
  179.  
  180. var tasks = new List<Task<int>>();
  181.  
  182. foreach (string f in filenames)
  183. {
  184. var t = new Task.Factory.StartNew<int>((arg) => {
  185. var lhits = 0;
  186. var fn = (string)arg;
  187.  
  188. byte[] bytes = File.ReadAllBytes(fn);
  189.  
  190. string contents = System.Text.Encoding.UTF8.GetString(bytes);
  191.  
  192. Match m = re.Match(contents);
  193.  
  194. while(m.Success)
  195. {
  196. lhits++;
  197. m = m.NextMatch();
  198. }
  199.  
  200. return lhits++;
  201. });
  202.  
  203. tasks.Add(t);
  204. }
  205.  
  206. tasks.WaitAll(tasks.ToArray());
  207.  
  208. var hits = 0;
  209. foreach (var t in tasks)
  210. hits += t.Result;
  211.  
  212. return hits;
  213. }
  214. ```
  215.  
  216. ### Wait All One by One Pattern
  217.  
  218. ```csharp
  219. private int SearchFiles(List<string> filenames, string pattern)
  220. {
  221. int hits = 0;
  222.  
  223. Regex re = new Regex(pattern, RegexOptions.Compiled | RegexOptions.Multipline);
  224.  
  225. var tasks = new List<Task<int>>();
  226.  
  227. foreach (string f in filenames)
  228. {
  229. var t = new Task.Factory.StartNew<int>((arg) => {
  230. var lhits = 0;
  231. var fn = (string)arg;
  232.  
  233. byte[] bytes = File.ReadAllBytes(fn);
  234.  
  235. string contents = System.Text.Encoding.UTF8.GetString(bytes);
  236.  
  237. Match m = re.Match(contents);
  238.  
  239. while(m.Success)
  240. {
  241. lhits++;
  242. m = m.NextMatch();
  243. }
  244.  
  245. return lhits++;
  246. });
  247.  
  248. tasks.Add(t);
  249. }
  250.  
  251. // tasks.WaitAll(tasks.ToArray());
  252. var results = WaitAllOneByOne(tasks);
  253.  
  254. // var hits = 0;
  255. // foreach (var t in tasks)
  256. // hits += t.Result;
  257. int hits = results.AsParallel().Sum();
  258.  
  259. return hits;
  260. }
  261.  
  262. private List<int> WaitAllOneByOne(List<Task<int> tasks)
  263. {
  264. var results = new List<int>();
  265.  
  266. while(tasks.Count > 0)
  267. {
  268. int i = Task.WaitAny(tasks.ToArray());
  269. results.Add(tasks[i].Result);
  270. tasks.RemoveAt(i);
  271. }
  272.  
  273. return results;
  274. }
  275. ```
  276.  
  277. ### Shared objects and non thread safe classes
  278.  
  279. ```csharp
  280. var results = new List<int>(); // non thread safe
  281. var rand = new Random(); // non thread safe
  282.  
  283. for (int i = 0; i < n; i++)
  284. {
  285. Task.Factory.StartNew(() => {
  286. int r = SimulationMethod(rand);
  287. results.Add(r);
  288. });
  289. }
  290. ```
  291.  
  292. ### Solution - Use thread safe classes
  293.  
  294. ```csharp
  295. var results = new ConcurrentQueue<int>();
  296.  
  297. for (int i = 0; i < n; i++)
  298. {
  299. Task.Factory.StartNew(() => {
  300. var rng = new RNGCryptoServiceProvider();
  301. var data = byte[4];
  302. rng.GetBytes(data);
  303. int seed = BitConverter.ToInt32(data, 0);
  304. var rand = new Random(seed);
  305.  
  306. int r = SimulationMethod(rand);
  307. results.Enqueue(r);
  308. });
  309. }
  310. ```
  311.  
  312. ### Solution 5 - Thread safe object
  313.  
  314. ```csharp
  315. var tasks = new List<Task<int>>();
  316.  
  317. private int SearchFiles(List<string> filenames, string pattern)
  318. {
  319. int hits = 0;
  320.  
  321. Regex re = new Regex(pattern, RegexOptions.Compiled | RegexOptions.Multipline);
  322.  
  323. var tasks = new List<Task<int>>();
  324.  
  325. foreach (string f in filenames)
  326. {
  327. var t = new Task.Factory.StartNew<int>((arg) => {
  328. var lhits = 0;
  329. var fn = (string)arg;
  330.  
  331. byte[] bytes = File.ReadAllBytes(fn);
  332.  
  333. // Non thread safe
  334. // string contents = System.Text.Encoding.UTF8.GetString(bytes);
  335. // Thread safe
  336. var encoding = new System.Text.UTF8Encoding();
  337. string contents = encoding.GetString(bytes)
  338.  
  339. Match m = re.Match(contents);
  340.  
  341. while(m.Success)
  342. {
  343. lhits++;
  344. m = m.NextMatch();
  345. }
  346.  
  347. return lhits++;
  348. });
  349.  
  350. tasks.Add(t);
  351. }
  352.  
  353. tasks.WaitAll(tasks.ToArray());
  354.  
  355. var hits = 0;
  356. foreach (var t in tasks)
  357. hits += t.Result;
  358.  
  359. return hits;
  360. }
  361. ```
  362. ### Solution 6 - Local object
  363.  
  364. ```csharp
  365. var tasks = new List<Task<int>>();
  366.  
  367. private int SearchFiles(List<string> filenames, string pattern)
  368. {
  369. int hits = 0;
  370.  
  371. // Regex re = new Regex(pattern, RegexOptions.Compiled | RegexOptions.Multipline);
  372.  
  373. var tasks = new List<Task<int>>();
  374.  
  375. foreach (string f in filenames)
  376. {
  377. var t = new Task.Factory.StartNew<int>((arg) => {
  378. var lhits = 0;
  379. var fn = (string)arg;
  380.  
  381. byte[] bytes = File.ReadAllBytes(fn);
  382.  
  383. var encoding = new System.Text.UTF8Encoding();
  384. string contents = encoding.GetString(bytes)
  385.  
  386. // Local object
  387. Regex re = new Regex(pattern, RegexOptions.Compiled | RegexOptions.Multipline);
  388. Match m = re.Match(contents);
  389.  
  390. while(m.Success)
  391. {
  392. lhits++;
  393. m = m.NextMatch();
  394. }
  395.  
  396. return lhits++;
  397. });
  398.  
  399. tasks.Add(t);
  400. }
  401.  
  402. tasks.WaitAll(tasks.ToArray());
  403.  
  404. var hits = 0;
  405. foreach (var t in tasks)
  406. hits += t.Result;
  407.  
  408. return hits;
  409. }
  410. ```
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement