Advertisement
Guest User

Untitled

a guest
Feb 26th, 2017
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.30 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <bits/stdc++.h>
  3. #include <pthread.h>
  4.  
  5. double *array;//the array to store data, length = n
  6. double *summleft;//the array to store the summ of the elements in
  7. //the progression which touches left border
  8. //of array part which belongs to a certain thread, length = p
  9. double *summright;//the array to store the summ of the elements in
  10. //the progression which touches right border
  11. //of array part which belongs to a certain thread, length = p
  12. int *numleft;//the array to store the amount of the elements in
  13. //the progression which touches left border
  14. //of array part which belongs to a certain thread, length = p
  15. int *numright;//the array to store the amount of the elements in
  16. //the progression which touches right border
  17. //of array part which belongs to a certain thread, length = p
  18. bool *isallthrough;//the array to check whether all elements of the array
  19. //part belonging to a certain thread are in one progression, length = p
  20.  
  21. typedef struct _ARGS
  22. {
  23. int length;
  24. int thread_num;
  25. int total_threads;
  26. int startpos;
  27. int thread_length;
  28. double right1;
  29. double right2;
  30. double left1;
  31. double left2;
  32. } ARGS;
  33.  
  34. void change_numbers(int length, int thread_num, int total_threads, int startpos, int thread_length, double right1, double right2, double left1, double left2);
  35. void *change_numbers_threaded(void* pa);
  36. void synchronize (int total_threads);
  37.  
  38. void synchronize(int total_threads)
  39. {
  40. static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  41. static pthread_cond_t condvar_in = PTHREAD_COND_INITIALIZER;
  42. static pthread_cond_t condvar_out = PTHREAD_COND_INITIALIZER;
  43. static int threads_in = 0;
  44. static int threads_out = 0;
  45. pthread_mutex_lock(&mutex);
  46. threads_in++;
  47. if (threads_in >= total_threads)
  48. {
  49. threads_out = 0;
  50. pthread_cond_broadcast(&condvar_in);
  51. }
  52. else
  53. {
  54. while (threads_in < total_threads)
  55. {
  56. pthread_cond_wait(&condvar_in, &mutex);
  57. }
  58. }
  59. threads_out++;
  60. if (threads_out >= total_threads)
  61. {
  62. threads_in = 0;
  63. pthread_cond_broadcast(&condvar_out);
  64. }
  65. else
  66. {
  67. while (threads_out < total_threads)
  68. {
  69. pthread_cond_wait(&condvar_out, &mutex);
  70. }
  71. }
  72. pthread_mutex_unlock(&mutex);
  73. }
  74.  
  75. void *change_numbers_threaded(void* pa)
  76. {
  77. ARGS* pargs = (ARGS*)pa;
  78. printf("Thread %d started\n", pargs->thread_num);
  79. change_numbers(pargs->length, pargs->thread_num, pargs->total_threads, pargs->startpos, pargs->thread_length, pargs->right1, pargs->right2, pargs->left1, pargs->left2);
  80. printf("Thread %d finished.\n", pargs->thread_num);
  81. return 0;
  82. }
  83.  
  84. int main(int argc, char** argv)
  85. {
  86. pthread_t *threads;
  87. ARGS* args;
  88. int nthreads;
  89. int length;
  90. double *rightnum1;//the element of the array after a certain thread, length = p
  91. double *rightnum2;//the 2nd element of the array after a certain thread, length = p
  92. double *leftnum1;//the element of the array before a certain thread, length = p
  93. double *leftnum2;//the 2nd element of the array before a certain thread, length = p
  94. double temp;
  95. int i,j;
  96.  
  97. if (argc<3)
  98. {
  99. printf("Execute the program with: a.out length total_threads [input]\n");
  100. return 1;
  101. }
  102.  
  103. nthreads=atoi(argv[2]);
  104. printf("The program will create %d threads.\n",nthreads);
  105. length=atoi(argv[1]);
  106. if(length<=0 || nthreads<=0)
  107. {
  108. printf("Cannot launch the program with these values for length and/or number of threads.\n");
  109. return 1;
  110. }
  111. if(length<nthreads)
  112. {
  113. printf("Several threads will not receive data. Lower the amount of threads.\n");
  114. return 1;
  115. }
  116. if(length<3)
  117. {
  118. printf("There cannot be any progressions in the array of less than 3 elements.\n");
  119. return 1;
  120. }
  121. if(nthreads*3>length)
  122. {
  123. printf("There will be thread processing less than 3 numbers. This is not normal.\nIf you want to continue, press 0\nIf you want to change the amount of threads, press 1\n");
  124. scanf("%d\n",&j);
  125. if(j!=0) return 1;
  126. }
  127.  
  128. array=new double[length];
  129. summleft=new double[nthreads];
  130. summright=new double[nthreads];
  131. numleft=new int[nthreads];
  132. numright=new int[nthreads];
  133. isallthrough=new bool[nthreads];
  134. threads=new pthread_t[nthreads];
  135. args=new ARGS[nthreads];
  136. if(!array || !summleft || !summright || !numleft || !numright || !isallthrough || !threads || !args)
  137. {
  138. if(array) delete[] array;
  139. if(summleft) delete[] summleft;
  140. if(summright) delete[] summright;
  141. if(numleft) delete[] numleft;
  142. if(numright) delete[] numright;
  143. if(isallthrough) delete[] isallthrough;
  144. if(threads) delete[] threads;
  145. if(args) delete[] args;
  146. printf("Not enough memory.\n");
  147. return -1;
  148. }
  149.  
  150. for(i=0;i<nthreads;i++)
  151. {
  152. summleft[i]=0;
  153. summright[i]=0;
  154. numleft[i]=0;
  155. numright[i]=0;
  156. isallthrough[i]=false;
  157. }
  158.  
  159. if(argc==3) for(i=0;i<length;i++) array[i]=i;
  160. else
  161. {
  162. FILE* fin;
  163. fin=fopen(argv[3], "r");
  164. if(!fin)
  165. {
  166. printf("File %s cannot be found and/or opened.\n",argv[3]);
  167. delete[] array;
  168. delete[] summleft;
  169. delete[] summright;
  170. delete[] numleft;
  171. delete[] numright;
  172. delete[] isallthrough;
  173. delete[] threads;
  174. delete[] args;
  175. return 1;
  176. }
  177. for(i=0;i<length;i++)
  178. {
  179. if(!fscanf(fin,"%lf",&temp))
  180. {
  181. printf("File %s contains less than %d numbers.\n",argv[3],length);
  182. fclose(fin);
  183. delete[] array;
  184. delete[] summleft;
  185. delete[] summright;
  186. delete[] numleft;
  187. delete[] numright;
  188. delete[] isallthrough;
  189. delete[] threads;
  190. delete[] args;
  191. return 2;
  192. }
  193. array[i]=temp;
  194. }
  195. if (fscanf(fin, "%lf", &temp) != EOF)
  196. {
  197. printf("File %s contains corrupted data.\n",argv[3]);
  198. fclose(fin);
  199. delete[] array;
  200. delete[] summleft;
  201. delete[] summright;
  202. delete[] numleft;
  203. delete[] numright;
  204. delete[] isallthrough;
  205. delete[] threads;
  206. delete[] args;
  207. return 3;
  208. }
  209. fclose(fin);
  210. }
  211.  
  212. printf("Input array:\n");
  213. for(i=0;i<length;i++) printf("%f\t",array[i]);
  214. printf("\n");
  215.  
  216. for(i=0;i<nthreads;i++)
  217. {
  218. args[i].thread_num=i;
  219. args[i].total_threads=nthreads;
  220. args[i].length=length;
  221. args[i].startpos=(int)(length/nthreads)*i;
  222. if(i<=length%nthreads) args[i].startpos+=i;
  223. else args[i].startpos+=length%nthreads;
  224. args[i].thread_length=length/nthreads;
  225. if(i<length%nthreads) args[i].thread_length++;
  226. if(i<nthreads-1) args[i].right1=array[args[i].startpos+args[i].thread_length];
  227. if(args[i].startpos+args[i].thread_length<length-1) args[i].right2=array[args[i].startpos+args[i].thread_length+1];
  228. if(i>0) args[i].left1=array[args[i].startpos-1];
  229. if(args[i].startpos-1>0) args[i].left2=array[args[i].startpos-2];
  230. }
  231.  
  232. for (i=0;i<nthreads;i++)
  233. {
  234. if(pthread_create(threads+i,0,change_numbers_threaded,args+i))
  235. {
  236. fprintf(stderr, "Cannot create thread #%d!", i);
  237. delete[] array;
  238. delete[] summleft;
  239. delete[] summright;
  240. delete[] numleft;
  241. delete[] numright;
  242. delete[] isallthrough;
  243. delete[] threads;
  244. delete[] args;
  245. return 10;
  246. }
  247. }
  248. for (i=0;i<nthreads;i++)
  249. {
  250. if (pthread_join(threads[i],0)) fprintf(stderr, "cannot wait thread #%d!", i);
  251. }
  252.  
  253. printf("Output array:\n");
  254. for(i=0;i<length;i++) printf("%f\t",array[i]);
  255. printf("\n");
  256. delete[] array;
  257. delete[] summleft;
  258. delete[] summright;
  259. delete[] numleft;
  260. delete[] numright;
  261. delete[] isallthrough;
  262. delete[] threads;
  263. delete[] args;
  264. return 0;
  265. }
  266.  
  267. void change_numbers(int length, int thread_num, int total_threads, int startpos, int thread_length, double right1, double right2, double left1, double left2)
  268. {
  269. int i,j=0;
  270. bool waitleft=false, waitright=false;
  271. int num=0;
  272. double average=0;
  273. printf("Thread %d works\n",thread_num);
  274. //printf("It received length=%d thread_num=%d total_threads=%d startpos=%d\n",length,thread_num, total_threads,startpos);
  275. //printf("It received right1=%f right2=%f left1=%f left2=%f\n",right1,right2,left1,left2);
  276. //printf("It received thread_length=%d\n",thread_length);
  277. if(thread_length>=3)//this part assumes that the length of this part is 3 elements or more.
  278. //NORMALLY this part has to work always
  279. {
  280.  
  281. if(fabs(array[startpos]-2*array[startpos+1]+array[startpos+2])<1e-9)//there is a progression touching left border
  282. {
  283. printf("Thread %d found a progression touching left border\n",thread_num);
  284. if(thread_num>0)
  285. {
  286. waitleft=true;
  287. printf("Thread %d waits left\n",thread_num);
  288. }
  289. for(i=0;i<thread_length;i++)//checked how many numbers in this part belong to
  290. //this progression, add this to border numbers.
  291. {
  292. if(fabs(array[startpos]-2*array[startpos+1]+array[startpos+2])>1e-9) break;
  293. summleft[thread_num]+=array[startpos+i];
  294. numleft[thread_num]++;
  295. }//the loop has ended but we need to add the last 2 manually
  296. //i has increased by 1 since the last addition, keep that in mind
  297. if(i<thread_length-2)
  298. {
  299. summleft[thread_num]+=array[startpos+i]+array[startpos+i+1];
  300. numleft[thread_num]+=2;
  301. }
  302. else if(i=thread_length-1)
  303. {
  304. summleft[thread_num]+=array[startpos+i];
  305. numleft[thread_num]++;
  306. }
  307. printf("Thread %d found %d elements in 1st progression with summ of %f\n",thread_num, numleft[thread_num],summleft[thread_num]);
  308. if(numleft[thread_num]==thread_length)//all array part belongs to the same progression
  309. {
  310. isallthrough[thread_num]=true;
  311. summright[thread_num]=summleft[thread_num];
  312. numright[thread_num]=numleft[thread_num];
  313. if(thread_num<total_threads-1) waitright=true;
  314. }
  315. }
  316.  
  317. if(fabs(array[startpos+thread_length-3]-2*array[startpos+thread_length-2]+array[startpos+thread_length-1])<1e-9 && !waitright)
  318. //there is a progression touching right border which does not go through all array part
  319. {
  320. if(thread_num<total_threads-1) waitright=true;
  321. for(i=thread_length;i>=numleft[thread_num];i--)
  322. //by default numleft[i]=0, if it is bigger, there are some numbers belonging to different progression
  323. //and these numbers can be skipped
  324. {
  325. if(fabs(array[startpos+thread_length-3]-2*array[startpos+thread_length-2]+array[startpos+thread_length-1])>1e-9) break;
  326. summright[thread_num]+=array[startpos+thread_length+i];
  327. numright[thread_num]++;
  328. }//the loop has ended but we need to add the last 2 manually
  329. //i has decreased by 1 since the last addition, keep that in mind
  330. summright[thread_num]+=array[startpos+thread_length+i]+array[startpos+thread_length+i-1];
  331. numright[thread_num]+=2;
  332. }
  333. }
  334. if(thread_length>=2)//this part assumes that there are at least 2 elements in this part of the array
  335. {
  336. if(thread_num!=0)
  337. {
  338. if(fabs(left1-2*array[startpos]+array[startpos+1])<1e-9)
  339. {
  340. if(!waitleft)//0|1,2,5,...|
  341. {
  342. summleft[thread_num]=array[startpos]+array[startpos+1];
  343. numleft[thread_num]=2;
  344. waitleft=true;
  345. }
  346. }
  347. }
  348. if(thread_num<total_threads-1)
  349. {
  350. if(fabs(array[startpos+thread_length-2]-2*array[startpos+thread_length-1]+right1)<1e-9)
  351. {
  352. if(!waitright)//|...,0,3,4|5
  353. {
  354. summright[thread_num]=array[startpos+thread_length-2]+array[startpos+thread_length-1];
  355. numright[thread_num]=2;
  356. waitright=true;
  357. }
  358. }
  359. }
  360. }
  361. //the next part will work even if the length of the part of the array is 1
  362. if(thread_num>0 && startpos-2>=0 && !waitleft)
  363. {
  364. if(fabs(left2-2*left1+array[startpos])<1e-9)//0,1|2,4,...|
  365. {
  366. summleft[thread_num]=array[startpos];
  367. numleft[thread_num]=1;
  368. waitleft=true;
  369. }
  370. }
  371. if(thread_num<total_threads-1 && startpos+thread_length+1<length && !waitright)
  372. {
  373. if(fabs(array[startpos+thread_length-1]-2*right1+right2)<1e-9)//|...,10,3|2,1
  374. {
  375. summright[thread_num]=array[startpos+thread_length-1];
  376. numright[thread_num]=1;
  377. waitright=true;
  378. }
  379. }
  380.  
  381. //what is yet to do is to check for isallthrough for ultrasmall array part sizes
  382. if(thread_length==2 && thread_num>0 && thread_num<total_threads-1)
  383. {
  384. if(fabs(left1+right1-array[startpos]-array[startpos+1])<1e-9)//0|1,2|3
  385. {
  386. isallthrough[thread_num]=true;
  387. }
  388. }
  389. if(thread_length==1 && thread_num>0 && thread_num<total_threads-1)
  390. {
  391. if(fabs(left1+right1-2*array[startpos])<1e-9)//0|1|2
  392. {
  393. isallthrough[thread_num]=true;
  394. }
  395. }
  396.  
  397. //The first part is finished. What is done:
  398. //If there is a progression touching left side or right side
  399. //of each array part, all of the threads will be able to know how many
  400. //numbers are in this progression, what is their summ and whether
  401. //this progression passes through all part of the array.
  402. //These elements require sync point to be changed properly. So now they are skipped.
  403. //We can still process the central part of the array part if it contains any
  404. //progressions which do not touch sides.
  405.  
  406. if(thread_length>=3)
  407. {
  408. for(i=numleft[thread_num];i<thread_length-numright[thread_num]-2;i++)
  409. {
  410. if(fabs(array[startpos+i]-2*array[startpos+1+i]+array[startpos+2+i])<1e-9)
  411. {
  412. while(fabs(array[startpos+i+num]-2*array[startpos+i+1+num]+array[startpos+i+2+num])<1e-9)
  413. {
  414. average+=array[startpos+i+num];
  415. num++;
  416. }
  417. average+=array[startpos+i+num]+array[startpos+i+num+1];
  418. num+=2;
  419. //we have found a progression from startpos+i to startpos+i+num
  420. average/=num;
  421. for(j=i;j<num+i;j++) array[startpos+j]=average;
  422. }
  423. average=0;
  424. num=0;
  425. i+=num;//we skip this progression so we don't work with it again
  426. }
  427. }
  428.  
  429. //What is only left is to process edges, we need a sync point for this.
  430.  
  431. synchronize(total_threads);
  432.  
  433. //After this sync point these arrays will never change:
  434. //summleft, summright, numleft, numright, isallthrough
  435. //This means that we can access them fully without any need of mutex.
  436.  
  437. if(waitleft)
  438. {
  439. average=summright[thread_num-1];
  440. num=numright[thread_num-1];
  441. i=1;
  442. while(isallthrough[thread_num-i])
  443. {
  444. average+=summright[thread_num-i-1];
  445. num+=numright[thread_num-i-1];
  446. i++;
  447. }
  448. for(i=0;i<numleft[thread_num];i++)
  449. {
  450. average+=array[startpos+i];
  451. num++;
  452. }
  453. average/=num;
  454. for(i=0;i<numleft[thread_num];i++) array[startpos+i]=average;
  455. }
  456.  
  457. if(waitright && !waitleft)
  458. {
  459. average=summleft[thread_num+1];
  460. num=numleft[thread_num+1];
  461. i=1;
  462. while(isallthrough[thread_num+i])
  463. {
  464. average+=summleft[thread_num+i+1];
  465. num+=numleft[thread_num+i+1];
  466. i++;
  467. }
  468. for(i=0;i<numright[thread_num];i++)
  469. {
  470. average+=array[startpos+thread_length-1-i];
  471. num++;
  472. }
  473. average/=num;
  474. for(i=0;i<numright[thread_num];i++) array[startpos+thread_length-1-i]=average;
  475. }
  476.  
  477. synchronize(total_threads);
  478. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement