Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Model Center   Code  
»áÔ±   
   
 
     
   
 ¶©ÔÄ
  ¾èÖú
ÔÚC++ÖÐʹÓÃopenmp½øÐжàÏ̱߳à³Ì
 
  11227  次浏览      27
 2018-10-29
 
±à¼­ÍƼö:
±¾ÎÄÀ´×ÔÓÚcsdn£¬±¾Îļòµ¥ÃèÊöÁËc++ÔÚ¶àÏ̵߳Äʵ¼Ê±à³ÌÖеÄÖØÒªÐÔ£¬Ï£Íû¶ÔÄúµÄѧϰÓаïÖú¡£

ǰÑÔ

¶àÏß³ÌÔÚʵ¼ÊµÄ±à³ÌÖеÄÖØÒªÐÔ²»ÑÔ¶øÓ÷¡£¶ÔÓÚC++¶øÑÔ£¬µ±ÎÒÃÇÐèҪʹÓöàÏß³Ìʱ£¬¿ÉÒÔʹÓÃboost::thread¿â»òÕß×Ô´ÓC++ 11¿ªÊ¼Ö§³ÖµÄstd::thread£¬Ò²¿ÉÒÔʹÓòÙ×÷ϵͳÏà¹ØµÄÏß³ÌAPI£¬ÈçÔÚLinuxÉÏ£¬¿ÉÒÔʹÓÃpthread¿â¡£³ý´ËÖ®Í⣬»¹¿ÉÒÔʹÓÃompÀ´Ê¹ÓöàÏ̡߳£ËüµÄºÃ´¦ÊÇ¿çÆ½Ì¨£¬Ê¹Óüòµ¥¡£

ÔÚLinuxƽ̨ÉÏ£¬Èç¹ûÐèҪʹÓÃomp£¬Ö»ÐèÔÚ±àÒëʱʹÓÃ"-fopenmp"Ö¸Áî¡£ÔÚWindowsµÄvisual studio¿ª·¢»·¾³ÖУ¬¿ªÆôompÖ§³ÖµÄ²½ÖèΪ¡°ÏîÄ¿ÊôÐÔ -> C/C++ -> ËùÓÐÑ¡Ïî -> openmpÖ§³Ö -> ÊÇ(/openmp)¡±¡£

±¾ÎÄÎÒÃǾͽéÉÜompÔÚC++ÖеÄʹÓ÷½·¨¡£

c++ openmpÈëÃżò½é

openmpÊÇÓÉһϵÁÐ#paragmaÖ¸Áî×é³É£¬ÕâЩָÁî¿ØÖÆÈçºÎ¶àÏ̵߳ÄÖ´ÐгÌÐò¡£ÁíÍ⣬¼´Ê¹±àÒëÆ÷²»Ö§³Öomp£¬³ÌÐòÒ²Ò²Äܹ»Õý³£ÔËÐУ¬Ö»ÊdzÌÐò²»»á¶àÏ̲߳¢ÐÐÔËÐС£ÒÔÏÂΪʹÓÃompµÄ¼òµ¥µÄÀý×Ó£º

int main()
{
vector<int> vecInt(100);
#pragma omp parallel for
for (int i = 0; i < vecInt.size(); ++i)
{
vecInt[i] = i*i;
}
return 0;
}

ÒÔÉÏ´úÂë»á×Ô¶¯ÒÔ¶àÏ̵߳ķ½Ê½ÔËÐÐforÑ­»·ÖеÄÄÚÈÝ¡£Èç¹ûÄãɾ³ý"#pragma omp parallel for"ÕâÐУ¬³ÌÐòÒÀÈ»Äܹ»Õý³£ÔËÐУ¬Î¨Ò»µÄÇø±ðÔÚÓÚ³ÌÐòÊÇÔÚµ¥Ïß³ÌÖÐÖ´ÐС£ÓÉÓÚCºÍC++µÄ±ê×¼¹æ¶¨£¬µ±±àÒëÆ÷Óöµ½ÎÞ·¨Ê¶±ðµÄ"#pragma"Ö¸Áîʱ£¬±àÒëÆ÷×Ô¶¯ºöÂÔÕâÌõÖ¸Áî¡£ËùÒÔ¼´Ê¹±àÒëÆ÷²»Ö§³Öomp£¬Ò²²»»áÓ°Ïì³ÌÐòµÄ±àÒëºÍÔËÐС£

ompÓï·¨

ËùÓеÄompÖ¸Áî¶¼ÊÇÒÔ"#pragma omp¡°¿ªÍ·£¬»»Ðзû½áÊø¡£²¢ÇÒ³ýÁËbarrierºÍflushÁ½¸öÖ¸Áî²»×÷ÓÃÓÚ´úÂëÒÔÍ⣬ÆäËûµÄÖ¸Áî¶¼Ö»ÓëÖ¸ÁîºóÃæµÄÄǶδúÂëÏà¹Ø£¬±ÈÈçÉÏÃæÀý×ÓÖеÄforÑ­»·¡£

parallel±àÒëָʾ

parallel¸æËß±àÒëÆ÷¿ªÊ¼ Ò»¸ö²¢Ðп飬±àÒëÆ÷»á´´½¨Ò»¸ö°üº¬N£¨ÔÚÔËÐÐʱ¾ö¶¨£¬Í¨³£ÎªÓ²¼þÏß³ÌÊý£©¸öÏ̵߳ÄÏß³Ì×飬ËùÓÐÏ̶߳¼ÔËÐнÓÏÂÀ´µÄÓï¾ä»òÕßÓÉ¡±{...}"°üº¬µÄ´úÂë¿é£¬ÔÚÕâÖ´ÐнáÊøÖ®ºó£¬Óֻص½Ö÷Ị̈߳¬´´½¨µÄÕâN¸öÏ̻߳ᱻ»ØÊÕ¡£

#pragma omp parallel
{
cout << "parallel run!!!\n";
}

ÒÔÉÏ´úÂëÔÚ4Ë«ºË4Ï̵߳ÄcpuµÄµçÄÔÉÏÔËÐÐʱ£¬Êä³öÁË4ÐС±parallel run!!!"¡£¼´±àÒëÆ÷´´½¨ÁËÒ»¸ö°üº¬4¸öÏ̵߳ÄÏß³Ì×éÀ´ÔËÐÐÕâ¶Î´úÂë¡£ÔÚÕâ¶Î´úÂëÔËÐнáÊøºó£¬³ÌÐòÖ´Ðлص½Ö÷Ï̡߳£GCC±àÒëÆ÷µÄʵÏÖ·½Ê½ÊÇÔÚÄÚ²¿´´½¨Ò»¸öº¯Êý£¬È»ºó½«Ïà¹ØµÄÖ´ÐдúÂëÒÆÖÁÕâ¸öº¯Êý£¬ÕâÑùÒ»À´´úÂë¿éÖж¨ÒåµÄ±äÁ¿³ÉΪÁËÏ̵߳ľֲ¿±äÁ¿£¬»¥²»Ó°Ïì¡£¶øICCµÄʵÏÖ·½Ê½ÊÇÀûÓÃfork()À´ÊµÏÖ¡£

Ïß³ÌÖ®¼ä¹²ÏíµÄ±äÁ¿ÊÇͨ¹ý´«µÝÒýÓûòÕßÀûÓÃregister±äÁ¿À´ÊµÏÖͬ²½µÄ£¬ÆäÖÐregister±äÁ¿ÔÚ´úÂëÖ´ÐнáÊøÖ®ºó»òÕßÔÚflushÖ¸Áîµ÷ÓÃʱ½øÐÐͬ²½¡£

ÎÒÃÇÒ²¿ÉÒÔÀûÓÃifÌõ¼þÅжÏÀ´¾ö¶¨ÊÇ·ñ¶ÔºóÐøµÄ´úÂë²ÉÓò¢Ðз½Ê½Ö´ÐУ¬È磺

externint parallelism_enabled;
#pragma omp parallel for if(parallelism_enabled)
for(int c=0; c<n;++c)
handle(c);

ÔÚÕâ¸öÀý×ÓÖУ¬Èç¹ûparallelism_enabledΪfalse£¬ÄÇôÕâ¸öforÑ­»·Ö»»áÓÉÒ»¸öÏß³ÌÀ´Ö´ÐС£

forÖ¸Áî

ompÖеÄforÖ¸ÁîÓÃÓÚ¸æËß±àÒëÆ÷£¬²ð·Ö½ÓÏÂÀ´µÄforÑ­»·£¬²¢·Ö±ðÔÚ²»Í¬µÄÏß³ÌÖÐÔËÐв»Í¬µÄ²¿·Ö¡£Èç¹ûforÖ¸ÁîºóûÓнô½Ó×ÅforÑ­»·£¬±àÒëÆ÷»á±¨´í¡£ÀýÈ磬

#pragma omp parallel for
for (int i = 0; i < 10; ++i)
{
printf("%d ", i);
}

ÒÔÉϵĴúÂëÖ´Ðк󣬻á´òÓ¡³ö[0,9]Õâ10¸öÊý×Ö¡£µ«ÊÇËüÃǵÄ˳ÐòÊÇËæ»ú³öÏֵģ¬ÔÚÎҵĵçÄÔÉÏ£¬ÔËÐеÄÊä³öÊÇ"0 1 2 8 9 6 7 3 4 5"¡£ÊÂʵÉÏ£¬Êä³ö½á¹û²»»áÊÇÍêÈ«Ëæ»úµÄ£¬Êä³öµÄÐòÁÐÊǾֲ¿ÓÐÐòµÄ£¬ÒòΪÔÚ±àÒëÆ÷¶ÔforÑ­»·µÄ²ð·ÖÏ൱ÓÚÏÂÃæµÄ´úÂ룺

int this_thread = omp_get_thread_num();
int num_threads = omp_get_num_threads();
int my_start = (this_thread)* 10 / num_threads;
int my_end = (this_thread + 1) * 10 / num_threads;
for (int n = my_start; n < my_end; ++n)
printf("%d ", n)

ÒÔÉÏ´úÂëÖУ¬omp_get_thread_num()ÓÃÓÚ»ñÈ¡µ±Ç°Ïß³ÌÔÚµ±Ç°Ïß³Ì×éÖеÄÐòºÅ£»omp_get_num_threads()ÓÃÓÚ»ñÈ¡ÏØ³Ç×éÖеÄÏß³ÌÊý¡£ËùÒÔÏß³Ì×éÖÐÿ¸öÏ̶߳¼ÔËÐÐÁËforÑ­»·ÖеIJ»Í¬²¿·Ö¡£

ÕâÀïÌáµ½forÑ­»·µÄ²»Í¬²¿·ÖÔÚÏß³Ì×éÖеIJ»Í¬Ïß³ÌÖÐÖ´Ðеģ¬Ïß³Ì×éÊÇÔÚ³ÌÐòÓöµ½"#pragma omp parallel"ʱ´´½¨£¬ÔÚ³ÌÐò¿é(parallelºóµÄ¡±{...}"»òÕßÓï¾ä)½áÊøºó£¬Ïß³Ì×éÖеÄÖ»ÓÐÒ»¸öÖ÷Ï̡߳£Òò´ËÉÏÃæÊ¾ÀýÖеĴúÂëÊÂʵÉÏÊÇÒÔÏ´úÂëµÄËõд£º

#pragma omp parallel
{
#pragma omp for
for (int i = 0; i < 10; ++i)
{
printf("%d ", i);
}
}

´Ë´¦µÄ"#pragma omp for"¼´Ê¹ÔÚ¡°#pragma omp parallel¡±Ö¸Áî´´½¨µÄÏß³Ì×éÖÐÖ´Ðеġ£¼ÓÈë´Ë´¦Ã»ÓÐ#pragma omp parallelÖ¸ÁÄÇôforÑ­»·Ö»»áÔÚÖ÷Ïß³ÌÖÐÖ´ÐС£parallelÖ¸ÁîËù´´½¨µÄÏß³Ì×éµÄÏß³ÌÊýĬÈÏÊÇÓбàÒëÆ÷¾ö¶¨µÄ£¬ÎÒÃÇÒ²¿ÉÒÔͨ¹ýnum_threadsÖ¸ÁîÀ´Ö¸¶¨Ïß³ÌÊý£¬È硱#pragma omp parallel num_threads(3)¡°¼´¸æËß±àÒëÆ÷£¬´Ë´¦ÐèÒª´´½¨Ò»¸ö°üº¬3¸öÏ̵߳ÄÏß³Ì×é¡£

ScheduleÖ¸Áî

ScheduleÖ¸ÁîÌṩ¶ÔforÖ¸ÁîÖÐÏ̵߳÷¶È¸ü¶àµÄ¿ØÖÆÄÜÁ¦¡£ËüÓÐÁ½ÖÖµ÷¶È·½Ê½£ºstaticºÍdynamic¡£

static£ºÃ¿¸öÏß³Ì×ÔÐоö¶¨ÒªÖ´ÐÐÄĸö¿é£¬¼´Ã¿¸öÏß³ÌÖ´ÐÐforÑ­»·ÖеÄÒ»¸ö×Ó¿é¡£

dynamic£ºÒ»¸öÏ̲߳¢²»ÊÇÖ´ÐÐforÑ­»·µÄÒ»¸ö×ӿ飬¶øÊÇÿ´Î¶¼ÏòompÔËÐÐʱ¿âË÷ȡһ¸öforÑ­»·Öеĵü´úÖµ£¬È»ºóÖ´ÐÐÕâ´Îµü´ú£¬ÔÚÖ´ÐÐÍêÖ®ºóÔÙË÷ȡеÄÖµ¡£Òò´Ë£¬Ïß³ÌÓпÉÄÜÖ´ÐÐÈÎÒâµÄµü´úÖµ£¬¶ø²»ÊÇÒ»¸ö×Ó¿é¡£

֮ǰµÄ¡±#pragma omp parallel for¡°Êµ¼ÊÉϵÄЧ¹ûÊÇ¡±#pragma omp parallel for schedule(static)"¡£Èç¹ûÎÒÃǽ«Ö®Ç°µÄʾÀý²ÉÓÃdynamicµ÷¶È·½Ê½£¬¼´£º

#pragma omp parallel for schedule(dynamic)
for (int i = 0; i < 10; ++i)
{
printf("%d ", i);
}

ÄÇô´òÓ¡µÄ½á¹ûÔòÓпÉÄܲ»ÊǾֲ¿ÓÐÐòµÄ¡£

ÔÚdynamicµ÷¶È·½Ê½ÖУ¬»¹¿ÉÒÔÖ¸¶¨Ã¿´ÎË÷È¡µÄµü´úÖµÊýÁ¿¡£È磬

#pragma omp parallel for schedule(dynamic£¬3)
for (int i = 0; i < 10; ++i)
{
printf("%d ", i);
}

ÔÚÕâ¸öÀý×ÓÖУ¬Ã¿¸öÏß³Ìÿ´Î¶¼Ë÷È¡3¸öµü´úÖµ¡£Ö´ÐÐÍêÖ®ºó£¬ÔÙÄÃ3¸öµü´úÖµ£¬Ö±µ½forÑ­»·ËùÓеü´úÖµ¶¼ÔËÐнáÊø¡£ÔÚ×îºóÒ»´ÎË÷È¡µÄ½á¹ûÓпÉÄܲ»×ã3¸ö¡£ÔÚ³ÌÐòÄÚ²¿£¬ÉÏÃæµÄÀý×ÓÓëÏÂÃæµÄ´úÂëÊǵȼ۵ģº

int a,b;
if(GOMP_loop_dynamic_start(0,10,1,3,&a,&b))
{
do{
for(int n=a; n<b;++n) printf(" %d", n);
}while(GOMP_loop_dynamic_next(&a,&b));
}

orderedÖ¸Áî

orderedÖ¸ÁîÓÃÓÚ¿ØÖÆÒ»¶Î´úÂëÔÚforÑ­»·ÖеÄÖ´ÐÐ˳Ðò£¬Ëü±£Ö¤Õâ¶Î´úÂëÒ»¶¨Êǰ´ÕÕforÖеÄ˳ÐòÒÀ´ÎÖ´Ðеġ£

for (int i = 0; i < 10; ++i)
{
Data data = ReadFile(files[i]);
#pragma omp ordered
PutDataToDataset(data);
}

Õâ¸öÑ­»·¸ºÔð¶ÁÈ¡10¸öÎļþ£¬È»ºó½«Êý¾Ý·ÅÈëÒ»¸öÄÚ´æ½á¹¹ÖС£¶ÁÎļþµÄ²Ù×÷ÊDz¢Ðе쬵«Êǽ«Êý¾Ý´æÈëÄÚ´æ½á¹¹ÖÐÔòÊÇÑϸñ´®Ðеġ£¼´ÏÈ´æµÚÒ»¸öÎļþÊý¾Ý£¬È»ºóµÚ¶þ¸ö...£¬×îºóÊǵÚÊ®¸öÎļþ¡£¼ÙÉèÒ»¸öÏß³ÌÒѾ­¶ÁÈ¡ÁËµÚÆß¸öÎļþµÄ£¬µ«ÊǵÚÁù¸öÎļþ»¹Ã»ÓдæÈëÄÚ´æ½á¹¹£¬ÄÇôÕâ¸öÏ̻߳á×èÈû£¬ÖªµÀµÚÁù¸öÎļþ´æÈëÄÚ´æ½á¹¹Ö®ºó£¬Ï̲߳Żá¼ÌÐøÔËÐС£

ÔÚÿһ¸öordered forÑ­»·ÖУ¬ÓÐÇÒ½öÓÐÒ»¸ö¡°#pragma omp ordered"Ö¸ÁîÏÞ¶¨µÄ´úÂë¿é¡£

sectionsÖ¸Áî

sectionÖ¸ÁîÓÃÓÚÖ¸¶¨ÄÄЩ³ÌÐò¿é¿ÉÒÔ²¢ÐÐÔËÐС£Ò»¸ösection¿éÄڵĴúÂë±ØÐë´®ÐÐÔËÐУ¬¶øsection¿éÖ®¼äÊÇ¿ÉÒÔ²¢ÐÐÔËÐеġ£È磬

#pragma omp parallel sections
{
{ Work1();}
#pragma omp section
{ Work2();
Work3();}
#pragma omp section
{ Work4();}
}

ÒÔÉÏ´úÂë±íÃ÷£¬work1£¬Work1,Work2 + Work3ÒÔ¼°Work4¿ÉÒÔ²¢ÐÐÔËÐУ¬µ«ÊÇwork2ºÍwork3µÄÔËÐбØÐëÊÇ´®ÐÐÔËÐУ¬²¢ÇÒÿ¸öwork¶¼Ö»»á±»ÔËÐÐÒ»´Î¡£

taskÖ¸Áî(OpenMP 3.0ÐÂÔö)

µ±¾õµÃforºÍsectionÖ¸ÁîÓÃ×Ų»·½±ãʱ£¬¿ÉÒÔÓÃtaskÖ¸Áî¡£ËüÓÃÓÚ¸æËß±àÒëÆ÷ÆäºóÐøµÄÖ¸Áî¿ÉÒÔ²¢ÐÐÔËÐС£ÈçOpenMP 3.0Óû§ÊÖ²áÉϵÄÒ»¸öʾÀý£º

struct node { node *left,*right;};
externvoid process(node*);
void traverse(node* p)
{
if(p->left)
#pragma omp task // p is firstprivate by default
traverse(p->left);
if(p->right)
#pragma omp task // p is firstprivate by default
traverse(p->right);
process(p);
}

ÉÏÃæµÄʾÀýÖУ¬µ±´¦Àíµ±Ç°½Úµãprocess(p)ʱ£¬²¢²»Äܹ»±£Ö¤pµÄ×óÓÒ×ÓÊ÷ÒѾ­´¦ÀíÍê±Ï¡£ÎªÁ˱£Ö¤ÔÚ´¦Àíµ±Ç°½Úµãǰ£¬µ±Ç°½ÚµãµÄ×óÓÒ×ÓÊ÷ÒѾ­´¦ÀíÍê³É£¬¿ÉÒÔʹÓÃtaskwaitÖ¸ÁÕâ¸öÖ¸Áî»á±£Ö¤Ç°ÃæµÄtask¶¼ÒѾ­´¦ÀíÍê³É£¬È»ºó²Å»á¼ÌÐøÍùÏÂ×ߣ¬Ìí¼ÓtaskwaitÖ¸ÁîÖ®ºó£¬ÒÔÉÏʾÀý´úÂë±äΪ£º

struct node { node *left,*right;};
externvoid process(node*);
void postorder_traverse(node* p)
{
if(p->left)
#pragma omp task // p is firstprivate by default
postorder_traverse(p->left);
if(p->right)
#pragma omp task // p is firstprivate by default
postorder_traverse(p->right);
#pragma omp taskwait
process(p);
}

ÒÔÏÂʾÀýÑÝʾÁËÈçºÎÀûÓÃtaskÖ¸ÁîÀ´²¢Ðд¦ÀíÁ´±íµÄÔªËØ£¬ÓÉÓÚÖ¸ÕëpĬÈÏÊÇfirstprivate·½Ê½¹²Ïí£¬ËùÒÔÎÞÐèÌØ±ðÖ¸¶¨¡£

struct node {int data; node* next;};
externvoid process(node*);
void increment_list_items(node* head)
{
#pragma omp parallel
{
#pragma omp single
{
for(node* p = head; p; p = p->next)
{
#pragma omp task
process(p);// p is firstprivate by default
}
}
}
}

atomicÖ¸Áî

atomicÖ¸ÁîÓÃÓÚ±£Ö¤ÆäºóÐøµÄÓï¾äÖ´ÐÐʱԭ×ÓÐԵġ£Ëùνԭ×ÓÐÔ£¬¼´ÊÂÎñµÄ¸ÅÄËüµÄÖ´Ðв»¿É²ð·Ö£¬ÒªÃ´Ö´Ðгɹ¦£¬ÒªÃ´Ê²Ã´¶¼Ã»ÓÐÖ´ÐС£ÀýÈ磬

#pragma omp atomic
counter += value;

ÒÔÉÏ´úÂëÖУ¬atomic±£Ö¤¶ÔcounterµÄ¸Ä±äʱԭ×ÓÐԵģ¬Èç¹û¶à¸öÏß³ÌͬʱִÐÐÕâ¾ä´úÂ룬ҲÄܹ»±£Ö¤counter×îÖÕÓµÓÐÕýÈ·µÄÖµ¡£

ÐèҪ˵Ã÷µÄÊÇ£¬atomicÖ»ÄÜÓÃÓÚ¼òµ¥µÄ±í´ïʽ£¬±ÈÈç+=¡¢-=¡¢*=¡¢&=µÈ£¬ËüÃÇͨ³£Äܹ»±»±àÒë³ÉÒ»ÌõÖ¸Áî¡£Èç¹ûÉÏÃæµÄʾÀý¸ÄΪ"counter = counter + value"£¬Äǽ«ÎÞ·¨Í¨¹ý±àÒ룻atomic×÷Óõıí´ïʽÖÐÒ²²»Äܹ»Óк¯Êýµ÷Óá¢Êý×éË÷ÒýµÈ²Ù×÷¡£ÁíÍ⣬ËüÖ»±£Ö¤µÈºÅ×ó±ß±äÁ¿µÄ¸³Öµ²Ù×÷µÄÔ­×ÓÐÔ£¬µÈºÅÓұߵıäÁ¿µÄȡֵ²¢²»ÊÇÔ­×ÓÐԵġ£Õâ¾ÍÒâζ×ÅÁíÍâÒ»¸öÏ߳̿ÉÄÜÔÚ¸³ÖµÇ°¸Ä±äµÈºÅÓұߵıäÁ¿¡£Èç¹ûÒª±£Ö¤¸ü¸´ÔÓµÄÔ­×ÓÐÔ¿ÉÒԲο¼ºóÐøµÄcriticalÖ¸Áî¡£

criticalÖ¸Áî

criticalÖ¸ÁîÓÃÓÚ±£Ö¤ÆäÏà¹ØÁªµÄ´úÂëÖ»ÔÚÒ»¸öÏß³ÌÖÐÖ´ÐС£ÁíÍ⣬ÎÒÃÇ»¹¿ÉÒÔ¸øcriticalÖ¸Áî´«µÝÒ»¸öÃû³Æ£¬Õâ¸öÃû³ÆÊÇÈ«¾ÖÐԵģ¬ËùÓоßÓÐÏàͬÃû×ÖµÄcriticalÏà¹ØÁªµÄ´úÂë±£Ö¤²»»áͬʱÔÚ¶à¸öÏß³ÌÖÐÔËÐУ¬Í¬Ò»Ê±¼ä×î¶àÖ»»áÓÐÒ»¸ö´úÂë¿éÔÚÔËÐС£Èç¹ûûÓÐÖ¸¶¨Ãû³Æ£¬ÄÇϵͳ»á¸ø¶¨Ò»¸öĬÈϵÄÃû³Æ£º

#pragma omp critical(dataupdate)
{
datastructure.reorganize();
}
...
#pragma omp critical(dataupdate)
{
datastructure.reorganize_again();
}

ÒÔÉÏ´úÂëչʾµÄÁ½¸öÃû³ÆÎª"dataupdate"µÄcritical´úÂëÒ»´ÎÖ»»áÓÐÒ»¸öÖ´ÐУ¬¼´datastructureµÄreorganize()ºÍreorganize_again()²»»á²¢ÐÐÔËÐУ¬Ò»´Î×î¶àÖ»»áÓÐÒ»¸öÔÚÏß³ÌÖÐÖ´ÐС£

openmpÖеÄËø

ompÔËÐпâÌṩÁËÒ»ÖÖËø£ºomp_lock_t£¬Ëü¶¨ÒåÔÚomp.hÍ·ÎļþÖС£Õë¶Ôomp_lock_tÓÐ5ÖвÙ×÷£¬ËüÃÇ·Ö±ðÊÇ£º

omp_init_lock³õʼ»¯Ëø£¬³õʼ»¯ºóËø´¦ÓÚÎ´Ëø¶¨×´Ì¬.

omp_destroy_lockÏú»ÙËø£¬µ÷ÓÃÕâ¸öº¯Êýʱ£¬Ëø±ØÐëÊÇÎ´Ëø¶¨×´Ì¬.

omp_set_lock³¢ÊÔ»ñÈ¡Ëø£¬Èç¹ûËøÒѾ­±»ÆäËûÏ̼߳ÓËøÁË£¬Äǵ±Ç°Ï߳̽øÈë×èÈû״̬¡£

omp_unset_lockÊÍ·ÅËø£¬µ÷ÓÃÕâ¸ö·½·¨µÄÏ̱߳ØÐëÒѾ­»ñµÃÁËËø£¬Èç¹ûµ±Ç°Ïß³ÌûÓлñµÃËø£¬Ôò»áÓÐ䶨ÒåÐÐΪ¡£

omp_test_locka³¢ÊÔ»ñÈ¡Ëø£¬»ñÈ¡Ëø³É¹¦Ôò·µ»Ø1£¬·ñÔò·µ»Ø0.

omp_lock_tÏ൱ÓÚmutex,Èç¹ûÏß³ÌÒѾ­»ñµÃÁËËø£¬ÄÇÔÚÊÍ·ÅËøÖ®Ç°£¬µ±Ç°Ï̲߳»ÄܶÔËø½øÐÐÉÏËø¡£ÎªÁËÂú×ãÕâÖֵݹéËøµÄÐèÇó£¬ompÌṩÁËomp_nest_lock_t£¬ÕâÖÖËøÏ൱ÓÚrecursive_mutex¿ÉÒԵݹéÉÏËø£¬µ«ÊÇÊͷŲÙ×÷±ØÐëÓëÉÏËø²Ù×÷Ò»Ò»¶ÔÓ¦£¬·ñÔòËø²»»áµÃµ½ÊÍ·Å¡£

flushÖ¸Áî

¶ÔÓÚ¶àÏß³ÌÖ®¼ä¹²ÏíµÄ±äÁ¿£¬±àÒëÆ÷ÓпÉÄܻὫËüÃÇÉèΪ¼Ä´æÆ÷±äÁ¿£¬Òâζ×Åÿ¸öÏß³ÌÊÂʵÉ϶¼Ö»ÊÇÓµÓÐÕâ¸ö±äÁ¿µÄ¸±±¾£¬µ¼Ö±äÁ¿Öµ²¢Ã»ÓÐÔÚ¶à¸öÏß³ÌÖ®¼ä¹²Ïí¡£ÎªÁ˱£Ö¤¹²Ïí±äÁ¿Äܹ»ÔÚÏß³ÌÖ®¼äÊÇÕæÊµ¹²Ïí£¬±£Ö¤Ã¿¸öÏ߳̿´µ½µÄÖµ¶¼ÊÇÒ»Öµģ¬¿ÉÒÔʹÓÃflushÖ¸Áî¸æËß±àÒëÆ÷ÎÒÃÇÐèÒªÄÄЩÄÄЩ¹²Ïí±äÁ¿¡£µ±ÎÒÃÇÒªÔÚ¶à¸öÏß³ÌÖжÁд¹²Í¬µÄ±äÁ¿Ê±£¬ÎÒÃǶ¼Ó¦¸ÃʹÓÃflushÖ¸Áî¡£

ÀýÈ磬

/* presumption: int a = 0, b = 0; */
/* First thread */ /* Second thread */
b =1; a =1;
#pragma omp flush(a,b) #pragma omp flush(a,b)
if(a ==0)if(b ==0)
{{
/* Critical section */ /* Critical section */
}}

ÔÚÉÏÃæµÄÀý×ÓÖУ¬±äÁ¿a,bÔÚÁ½¸öÏß³ÌÖÐÊǹ²ÏíµÄ£¬Á½¸öÏß³ÌÈκÎʱºò¿´µ½µÄa,bµÄÖµ¶¼ÊÇÒ»Öµģ¬¼´Ïß³Ì1Ëù¼ûµÄ¼´Ê¹Ïß³Ì2Ëù¼ûµÄ¡£

private,firstprivate,lastprivate¼°sharedÖ¸Áî¿ØÖÆ±äÁ¿¹²Ïí·½Ê½

ÕâЩָÁîÓÃÓÚ¿ØÖƱäÁ¿ÔÚÏß³Ì×éÖжà¸öÏß³ÌÖ®¼äµÄ¹²Ïí·½Ê½¡£ÆäÖÐprivate,firstprivate,lastprivate±íʾ±äÁ¿µÄ¹²Ïí·½Ê½ÊÇ˽Óе쬼´Ã¿¸öÏ̶߳¼ÓÐÒ»·Ý×Ô¼ºµÄ¿½±´£»¶øshared±íʾÏß³Ì×éµÄÏ̷߳ÃÎʵÄÊÇͬһ¸ö±äÁ¿¡£

˽ÓбäÁ¿¹²Ïí·½Ê½ÓÐÈýÖÖÖ¸ÁËüÃǵÄÇø±ðÔÚÓÚ£º

private:ÿ¸öÏ̶߳¼ÓÐÒ»·Ý×Ô¼ºµÄ¿½±´£¬µ«ÊÇÕâЩ±äÁ¿²¢Ã»Óп½±´Öµ£¬¼´Èç¹û±äÁ¿ÊÇint,long,doubleµÈÕâЩÄÚÖÃÀàÐÍ£¬ÄÇôÕâЩ±äÁ¿ÔÚ½øÈëÏß³Ìʱʱδ³õʼ»¯×´Ì¬µÄ£»Èç¹û±äÁ¿ÊÇÀàµÄʵÀý¶ÔÏó£¬ÄÇôÔÚÏß³ÌÖбäÁ¿ÊÇͨ¹ýĬÈϹ¹ÔìµÃµ½µÄ¶ÔÏ󣬼ÙÉèÀàûÓÐĬÈϹ¹Ô죬Ôò±àÒë»á±¨´í£¬¸æËßÄãÀàûÓпÉÓõÄĬÈϹ¹Ô죻

firstPrivate:ÿ¸öÏß³ÌÓÐÒ»·Ý×Ô¼ºµÄ¿½±´£¬Ã¿¸öÏ̶߳¼»áͨ¹ý¸´ÖÆÒ»·Ý¡£Èç¹û±äÁ¿ÊÇint,long,doubleµÈÄÚÖÃÀàÐÍÔòÖ±½Ó¸´ÖÆ£¬Èç¹ûΪÀàµÄʵÀý¶ÔÏó£¬Ôò»áµ÷ÓÃʾÀý¶ÔÏóµÄ¿½±´¹¹Ô캯Êý£¬Õâ¾ÍÒâζ×Å£¬¼ÙÈçÀàÊǵĿ½±´¹¹Ôì²»¿É·ÃÎÊ£¬Ôò±äÁ¿²»Äܹ»Ê¹ÓÃfirstprivate·½Ê½¹²Ïí£»

lastprivate:±äÁ¿ÔÚÿ¸öÏ̵߳Ĺ²Ïí·½Ê½ÓëprivateÒ»Ö£¬µ«²»Í¬µÄÊÇ£¬±äÁ¿µÄ×îºóÒ»´Îµü´úÖеÄÖµ»áflush»áÖ÷Ïß³ÌÖеıäÁ¿ÖС£×îºóÒ»´Îµü´úµÄÒâ˼ÊÇ£¬Èç¹ûÊÇforÑ­»·£¬ÔòÖ÷Ï̵߳ıäÁ¿µÄÖµÊÇ×îºóÒ»¸öµü´úÖµÄǴεü´úÖи³µÄÖµ£»Èç¹ûÊÇsection£¬ÔòÖ÷Ï̵߳ıäÁ¿×îÖÕµÄÖµÊÇ×îºóÒ»¸ösectionÖи³µÄÖµ¡£Òª×¢ÒâµÄÊÇ£¬×îÖÕÖ÷Ï̵߳ÄÖбäÁ¿µÄÖµ²¢·Çͨ¹ý¿½±´¹¹Ô츳ֵµÄ£¬¶øÊÇͨ¹ýoperator=²Ù×÷·û£¬ËùÒÔÈç¹ûÀàµÄ¸³Öµ²Ù×÷·û²»¿É·ÃÎÊ£¬ÄÇô±äÁ¿²»ÄܲÉÓÃlastprivate·½Ê½¹²Ïí¡£

defaultÖ¸Áî

defaultÃüÁîÓÃÓÚÉèÖÃËùÓбäÁ¿µÄĬÈϵĹ²Ïí·½Ê½£¬Èçdefault(shared)±íʾËùÓбäÁ¿Ä¬ÈϹ²Ïí·½Ê½Îªshared¡£³ý´ËÖ®Í⣬ÎÒÃÇ¿ÉÒÔʹÓÃdefault(none)À´¼ì²éÎÒÃÇÊÇ·ñÏÔʾÉèÖÃÁËËùÓÐʹÓÃÁ˵ıäÁ¿µÄ¹²Ïí·½Ê½£¬È磺

int a, b=0;
#pragma omp parallel default(none) shared(b)
{
b += a;
}

ÒÔÉÏ´úÂëÎÞ·¨Í¨¹ý±àÒ룬ÒòΪÔÚparallelµÄ´úÂë¿éÖÐʹÓÃÁ˱äÁ¿aºÍb£¬µ«ÊÇÎÒÃÇÖ»ÉèÖÃÁËbµÄ¹²Ïí·½Ê½£¬¶øÃ»ÓÐÉèÖñäÁ¿aµÄ¹²Ïí·½Ê½¡£

ÁíÍâÐèҪעÒâµÄÊÇ£¬defaultÖеIJÎÊý²»ÄÜʹÓÃprivate¡¢firstprivateÒÔ¼°lastprivate¡£

reductionÖ¸Áî

reductinoÖ¸ÁîÊÇprivate,shared¼°atomicµÄ×ÛºÏÌå¡£ËüµÄÓï·¨ÊÇ£º

reduction(operator : list)

ÆäÖÐoperatorÖ¸²Ù×÷·û£¬list±íʾ²Ù×÷·ûÒª×÷ÓõÄÁÐ±í£¬Í¨³£ÊÇÒ»¸ö¹²Ïí±äÁ¿Ãû£¬Ö®ËùÒÔ³ÆÖ®ÎªÁбíÊÇÒòΪÏß³Ì×éÖеÄÿ¸öÏ̶߳¼ÓÐÒ»·Ý±äÁ¿µÄ¿½±´£¬reduction¼´¸ºÔðÓøø¶¨µÄ²Ù×÷·û½«ÕâЩ¿½±´µÄ¾Ö²¿±äÁ¿µÄÖµ½øÐоۺϣ¬²¢ÉèÖûع²Ïí±äÁ¿¡£

ÆäÖвÙ×÷·û¿ÉÒÔÊÇÈçϵIJÙ×÷·û£º

ÒÔÏÂΪ½×³ËµÄ¶àÏ̵߳ÄʵÏÖ£º

int factorial(int number)
{
int fac =1;
#pragma omp parallel for reduction(*:fac)
for(int n=2; n<=number;++n)
fac *= n;
return fac;
}

¿ªÊ¼£¬Ã¿¸öÏ̻߳´±´Ò»·Ýfac£»

parallel¿é½áÊøÖ®ºó£¬Ã¿¸öÏß³ÌÖеÄfac»áÀûÓá°*¡±½øÐоۺϣ¬²¢½«¾ÛºÏµÄ½á¹ûÉèÖûØÖ÷Ïß³ÌÖеÄfacÖС£

Èç¹ûÕâÀïÎÒÃDz»ÓÃreduction£¬ÄÇôÔòÐèÓÃÊÊÓÃatomicÖ¸Á´úÂëÈçÏ£º

int factorial(int number)
{
int fac =1;
#pragma omp parallel for
for(int n=2; n<=number;++n)
{
#pragma omp atomic
fac *= n;
}
return fac;
}

µ«ÊÇÕâÑùÒ»À´£¬ÐÔÄÜ»á´ó´óµÄϽµ£¬ÒòΪÕâÀïûÓÐʹÓþֲ¿±äÁ¿£¬Ã¿¸öÏ̶߳ÔfacµÄ²Ù×÷¶¼ÐèÒª½øÐÐͬ²½¡£ËùÒÔÔÚÕâ¸öÀý×ÓÖУ¬²¢²»»á´Ó¶àÏß³ÌÖÐÊÜÒæ¶àÉÙ£¬ÒòΪatomic³ÉΪÁËÐÔÄÜÆ¿¾±¡£

ʹÓÃreductionÖ¸ÁîµÄ´úÂëÊÂʵÉÏÀàËÆÓÚÒÔÏ´úÂ룺

int factorial(int number)
{
int fac =1;
#pragma omp parallel
{
int fac_private =1;
#pragma omp for nowait
for(int n=2; n<=number;++n)
fac_private *= n;
#pragma omp atomic
fac *= fac_private;
}
return fac;
}

×¢£º×îºóµÄ¾ÛºÏʵ¼ÊÊǰüÀ¨Ö÷Ïß³ÌÖй²Ïí±äÁ¿µÄ³õʼֵһÆðµÄ£¬Ôڽ׳˵ÄÀý×ÓÖУ¬Èç¹ûfacµÄ³õʼֵ²»ÊÇ1£¬¶øÊÇ10£¬Ôò×îÖյĽá¹û»áÊÇʵ¼Ê½×³ËÖµµÄ10±¶£¡

barrierºÍnowaitÖ¸Áî

barrierÖ¸ÁîÊÇÏß³Ì×éÖÐÏ̵߳ÄÒ»¸öͬ²½µã£¬Ö»ÓÐÏß³Ì×éÖеÄËùÓÐÏ̶߳¼µ½´ïÕâ¸öλÖÃÖ®ºó£¬²Å»á¼ÌÐøÍùÏÂÔËÐС£¶øÔÚÿ¸öfor¡¢sectionÒÔ¼°ºóÃæÒª½²µ½µÄsingle´úÂë¿é×îºó¶¼ÒþʽµÄÉèÖÃÁËbarrierÖ¸Áî¡£ÀýÈç

#pragma omp parallel
{
/* All threads execute this. */
SomeCode();
#pragma omp barrier
/* All threads execute this, but not before
* all threads have finished executing SomeCode().
*/
SomeMoreCode();
}

nowaitÖ¸ÁîÓÃÀ´¸æËß±àÒëÆ÷ÎÞÐèÒþʽµ÷ÓÃbarrierÖ¸ÁÒò´ËÈç¹ûΪfor¡¢section¡¢singleÉèÖÃÁËnowait±êÖ¾£¬ÔòÔÚËüÃÇ×îºó²»»áÒþʽµÄµ÷ÓÃbarrierÖ¸ÁÀýÈ磺

#pragma omp parallel
{
#pragma omp for
for(int n=0; n<10;++n) Work();
// This line is not reached before the for-loop is completely finished
SomeMoreCode();
}

// This line is reached only after all threads from
// the previous parallel block are finished.
CodeContinues();

#pragma omp parallel
{
#pragma omp for nowait
for(int n=0; n<10;++n) Work();
// This line may be reached while some threads are still executing the for-loop.
SomeMoreCode();
}

// This line is reached only after all threads from
// the previous parallel block are finished.
CodeContinues();

singleºÍmasterÖ¸Áî

singleÖ¸ÁîÏà¹ØµÄ´úÂë¿éÖ»ÔËÐÐÒ»¸öÏß³ÌÖ´ÐУ¬µ«²¢²»ÏÞ¶¨¾ßÌåÄÄÒ»¸öÏß³ÌÀ´Ö´ÐУ¬ÆäËüÏ̱߳ØÐëÌø¹ýÕâ¸ö´úÂë¿é£¬²¢ÔÚ´úÂë¿éºówait£¬Ö±µ½Ö´ÐÐÕâ¶Î´úÂëµÄÏß³ÌÍê³É¡£

#pragma omp parallel
{
Work1();
#pragma omp single
{
Work2();
}
Work3();
}

ÒÔÉÏ´úÂëÖУ¬work1()ºÍwork3()»áÔÚÏß³Ì×éÖÐËùÓÐÏ̶߳¼ ÔËÐÐÒ»±é£¬µ«ÊÇwork2()Ö»»áÔÚÒ»¸öÏß³ÌÖÐÖ´ÐУ¬¼´Ö»»áÖ´ÐÐÒ»±é¡£

masterÖ¸ÁîÔòÖ¸¶¨ÆäÏà¹ØµÄ´úÂë¿é±ØÐëÔÚÖ÷Ïß³ÌÖÐÖ´ÐУ¬ÇÒÆäËüÏ̲߳»±ØÔÚ´úÂë¿éºó×èÈû¡£

#pragma omp parallel
{
Work1();
// This...
#pragma omp master
{
Work2();
}
// ...is practically identical to this:
if(omp_get_thread_num()==0)
{
Work2();
}

Work3();
}

Ñ­»·Ç¶Ì×

ÈçÏ´úÂë²¢²»»á°´ÕÕÎÒÃÇÆÚÍûµÄ·½Ê½ÔËÐУº

#pragma omp parallel for
for(int y=0; y<25;++y)
{
#pragma omp parallel for
for(int x=0; x<80;++x)
{
tick(x,y);
}
}

ʵ¼ÊÉÏÄÚ²¿µÄÄǸö¡°parallel for"»á±»ºöÂÔ£¬×ÔʼÖÁÖÕÖ»´´½¨ÁËÒ»¸öÏß³Ì×é¡£¼ÙÈ罫ÉÏÊö´úÂë¸ÄΪÈçÏÂËùʾ£¬½«ÎÞ·¨Í¨¹ý±àÒ룺

#pragma omp parallel for
for(int y=0; y<25;++y)
{
#pragma omp for // ERROR, nesting like this is not allowed.
for(int x=0; x<80;++x)
{
tick(x,y);
}
}

OpenMP 3.0ÖеĽâ¾ö·½°¸

ÔÚOpenMP 3.0ÖУ¬¿ÉÒÔÀûÓÃcollapseÖ¸ÁîÀ´½â¾öÑ­»·Ç¶Ì×ÎÊÌ⣬È磺

#pragma omp parallel for collapse(2)
for(int y=0; y<25;++y)
for(int x=0; x<80;++x)
{
tick(x,y);
}

collapseÖ¸Áî´«µÝµÄÊý×־ʹú±íÁËÑ­»·Ç¶Ì×µÄÉî¶È£¬ÕâÀïΪ2²ã¡£

OpenMP 2.5ÖÐÕýÈ·µÄ×ö·¨

ÔÚOpenMP 2.5ÖУ¬ÎÒÃÇ¿ÉÒÔͨ¹ý½«¶à²ãÑ­»·¸ÄΪµ¥²ãÑ­»·µÄ·½·¨À´´ïµ½Ä¿µÄ£¬ÕâÑù±ãÎÞÐèÑ­»·Ç¶Ì×:

#pragma omp parallel for
for(int pos=0; pos<(25*80);++pos)
{
int x = pos%80;
int y = pos/80;
tick(x,y);
}

È»¶øÖØÐ´ÕâÑùµÄ´úÂëÒ²²¢·ÇÒ×Ê£¬ÁíÒ»¸ö°ì·¨ÊDzÉÓÃomp_set_nested·½·¨¿ªÆôÑ­»·Ç¶Ì×Ö§³Ö£¬Ä¬ÈÏÊǹرյģº

omp_set_nested(1);
#pragma omp parallel for
for(int y=0; y<25;++y)
{
#pragma omp parallel for
for(int x=0; x<80;++x)
{
tick(x,y);
}
}

ÏÖÔÚÄÚ²ãÑ­»·ÖУ¬Ò²»á´´½¨Ò»¸ö´óСΪNµÄÏß³Ì×飬Òò´Ëʵ¼ÊÉÏÎÒÃǽ«µÃµ½N*N¸öỊ̈߳¬Õâ±ã»áµ¼ÖÂÆµ·±µÄÏß³ÌÇл»£¬»á´øÀ´½Ï´óµÄÐÔÄÜËðʧ£¬ÕâÒ²¾ÍÊÇΪʲôѭ»·Ç¶Ì×ĬÈÏÊǹرյġ£Ò²Ðí×îºÃµÄ·½·¨¾ÍÊǽ«Íâ²ãÑ­»·µÄparallelÖ¸Áîɾ³ý£¬Ö»±£ÁôÄÚ²ãÑ­»·µÄparallel£º

for(int y=0; y<25;++y)
{
#pragma omp parallel for
for(int x=0; x<80;++x)
{
tick(x,y);
}
}

È¡ÏûỊ̈߳¨Í˳öÑ­»·£©

constchar* FindAnyNeedle(constchar* haystack, size_t size,char needle)
{
for(size_t p =0; p < size;++p)
if(haystack[p]== needle)
{return haystack+p; //ÕÒµ½needle£¬Ö±½ÓÍ˳öº¯Êý
}
return NULL;
}

¼ÓÈëÎÒÃÇÏëҪʹÓÃomp¶àÏß³ÌÀ´ÓÅ»¯ÈçÏ·½·¨£º

ÎÒÃÇ×îÖ±¹ÛµÄÏë·¨Ó¦¸ÃÊÇÔÚforÑ­»·Íâ¼ÓÉÏ¡°#pragma omp parallel for"£¬µ«ÊÇÈÃÈËʧÍûµÄÊÇÕ⽫ÎÞ·¨Í¨¹ý±àÒë¡£ÒòΪompÒªÇó±ØÐëÿ¸öÑ­»·µü´ú¶¼Äܵõ½´¦Àí£¬Òò´Ë²»ÔÊÐíÖ±½ÓÍ˳öÑ­»·£¬ÕâÒ²¾ÍÊÇ˵ÔÚÑ­»·Öв»ÄÜʹÓÃreturn¡¢break¡¢goto¡¢throwµÈÄܹ»ÖжÏÑ­»·µÄÓï¾ä¡£ÎªÁËÄܹ»ÌáǰÍ˳öÑ­»·£¬ÎÒÃÇÐèÒªÍ˳öʱ£¬Í¨ÖªÏß³Ì×éµÄÆäËûỊ̈߳¬ÈÃËüÃǽáÊøÔËÐУº

ÆúÓÃomp£¬Ñ¡ÔñÆäËû¶àÏ̱߳à³Ì£¬Èçpthread

ͨ¹ý¹²Ïí±äÁ¿£¬Í¨ÖªÏß³Ì×éÆäËûÏß³Ì

ÒÔÏÂΪʹÓò¼¶û±ê¼ÇÀ´Í¨ÖªÆäËûÏ̵߳ÄʾÀý£º

constchar* FindAnyNeedle(constchar* haystack, size_t size,char needle)
{
constchar* result = NULL;
bool done =false;
#pragma omp parallel for
for(size_t p =0; p < size;++p)
{
#pragma omp flush(done)
if(!done)
{
/* Do work only if no thread has found the needle yet. */
if(haystack[p]== needle)
{
/* Inform the other threads that we found the needle. */
done =true;
#pragma omp flush(done)
result = haystack+p;
}
}
}
return result;
}

È»¶øÕâÑùдÓиöȱµã¾ÍÊÇ£¬¼´Ê¹done±ê¼Ç±äΪtrueÁË£¬ÆäËûÏß³ÌÈÔÈ»ÐèÒªÍê³Éÿ´Îµü´ú£¬¼´Ê¹ÕâЩµü´úÊÇÍêȫûÓÐÒâÒåµÄ¡£. µ±È»£¬ÎÒÃÇÒ²¿ÉÒÔ²»ÓÃÉÏÊöµÄdone±ê¼Ç£º

constchar* FindAnyNeedle(constchar* haystack, size_t size,char needle)
{
constchar* result = NULL;
#pragma omp parallel for
for(size_t p =0; p < size;++p)
if(haystack[p]== needle)
result = haystack+p;
return result;
}

µ«ÊÇÕâÒ²²¢Ã»ÓÐÍêÈ«½â¾öÎÊÌ⣬ÒòΪÕâÑùµ±Ò»¸öÏß³ÌÒѾ­ÕÒµ½ÐèÒªµÄ½á¹ûÊÇ£¬Ò²²»Äܹ»±ÜÃâÆäËûÏ̼߳ÌÐøÔËÐУ¬ÕâÒ²¾ÍÔì³ÉÁ˲»±ØÒªµÄÀË·Ñ¡£

ÊÂʵÉÏ£¬ompÕë¶ÔÕâ¸öÎÊÌⲢûÓкܺõĽâ¾ö°ì·¨£¬Èç¹ûȷʵÐèÒª£¬ÄÇÖ»ÄÜÇóÖúÓÚÆäËûÏ߳̿âÁË¡£

 

   
11227 ´Îä¯ÀÀ       27
Ïà¹ØÎÄÕÂ

Éî¶È½âÎö£ºÇåÀíÀôúÂë
ÈçºÎ±àд³öÓµ±§±ä»¯µÄ´úÂë
ÖØ¹¹-ʹ´úÂë¸ü¼ò½àÓÅÃÀ
ÍŶÓÏîÄ¿¿ª·¢"±àÂë¹æ·¶"ϵÁÐÎÄÕÂ
Ïà¹ØÎĵµ

ÖØ¹¹-¸ÄÉÆ¼ÈÓдúÂëµÄÉè¼Æ
Èí¼þÖØ¹¹v2
´úÂëÕû½àÖ®µÀ
¸ßÖÊÁ¿±à³Ì¹æ·¶
Ïà¹Ø¿Î³Ì

»ùÓÚHTML5¿Í»§¶Ë¡¢Web¶ËµÄÓ¦Óÿª·¢
HTML 5+CSS ¿ª·¢
ǶÈëʽC¸ßÖÊÁ¿±à³Ì
C++¸ß¼¶±à³Ì