OpenMP并行编程

2023-11-03

1.总览

  OpenMP(Open Multi-Processing)是一种用于共享内存并行系统的多线程程序设计方案,支持的编程语言包括C、C++和Fortran。OpenMP提供了对并行算法的高层抽象描述,通过线程实现并行化,特别适合在多核CPU机器上的并行程序设计。编译器根据程序中添加的pragma指令,自动将程序并行处理,使用OpenMP降低了并行编程的难度和复杂度。当编译器不支持OpenMP时,程序会退化成普通(串行)程序。程序中已有的OpenMP指令不会影响程序的正常编译运行。

OpenMP与Pthread有着许多本质不同:

  • Pthread需要显式地明确每个线程的行为; OpenMP只需要简单的声明这块代码并行执行。
  • 只要系统拥有Pthreads库,Pthreads程序就能够被任意的C编译器使用;除了拥有OpenMP还要求编译器支持某些操作。
  • Pthreads提供了虚拟地编写任何可知线程行为的能力;OpenMP用于实现并行更加简单,但是很难对底层的线程交互进行编程。

OpenMP采用fork-join的执行模式。开始的时候只存在一个主线程,当需要进行并行计算的时候,派生出若干个分支线程来执行并行任务。当并行代码执行完成之后,分支线程会合,并把控制流程交给单独的主线程。

Fork(派生):主线程(master thread)创建一组并行化执行的线程;
Join(合并):当线程完成工作后,它们会进行同步与终止,只剩下master thread。
在这里插入图片描述

2.编译

使用gcc编译OpenMP程序,需要在后面包含-fopenmp选项;

在VS中启用OpenMP,在项目上右键 -> 属性 -> 配置属性 ->C/C++ -> 语言 -> OpenMP支持,选择“是”即可。

3.编译制导指令

编译制导指令以#pragma omp开始,后面根具体的功能指令,格式如:#pragma omp 指令[子句,[子句]…]。常用的功能指令如下:

  • parallel:用在一个结构块之前,表示这段代码将被多个线程并行执行;
  • for:用于for循环语句之前,表示将循环计算任务分配到多个线程中并行执行,以实现任务分担,必须由编程人员自己保证每次循环之间无数据相关性;
  • parallel for: parallel和for指令的结合,也是用在for循环语句之前,表示for循环体的代码将被多个线程并行执行,它同时具有并行域的产生和任务分担两个功能;
  • sections:用在可被并行执行的代码段之前,用于实现多个结构块语句的任务分担,可并行执行的代码段各自用section指令标出(注意区分sections和section);
  • parallel sections:parallel和sections两个语句的结合,类似于parallel for;
  • single:用在并行域内,表示一段只被单个线程执行的代码;
  • critical:用在一段代码临界区之前,保证每次只有一个OpenMP线程进入;
  • flush:保证各个OpenMP线程的数据影像的一致性;
  • barrier:用于并行域内代码的线程同步,线程执行到barrier时要停下等待,直到所有线程都执行到barrier时才继续往下执行;
  • atomic:用于指定一个数据操作需要原子性地完成;
  • master:用于指定一段代码由主线程执行;
  • threadprivate:用于指定一个或多个变量是线程专用;

相应的OpenMP子句为:

  • private:指定一个或多个变量在每个线程中都有它自己的私有副本;
  • firstprivate:指定一个或多个变量在每个线程都有它自己的私有副本,并且私有变量要在进入并行域或任务分担域时,继承主线程中的同名变量的值作为初值;
  • lastprivate:是用来指定将线程中的一个或多个私有变量的值在并行处理结束后复制到主线程中的同名变量中,负责拷贝的线程是for或sections任务分担中的最后一个线程;
  • reduction:用来指定一个或多个变量是私有的,并且在并行处理结束后这些变量要执行指定的归约运算,并将结果返回给主线程同名变量;
  • nowait:指出并发线程可以忽略其他制导指令暗含的路障同步;
  • num_threads:指定并行域内的线程的数目;
  • schedule:指定for任务分担中的任务分配调度类型;
  • shared:指定一个或多个变量为多个线程间的共享变量;
  • ordered:用来指定for任务分担域内指定代码段需要按照串行循环次序执行;
  • copyprivate:配合single指令,将指定线程的专有变量广播到并行域内其他线程的同名变量中;
  • copyin:用来指定一个threadprivate类型的变量需要用主线程同名变量进行初始化;
  • default:用来指定并行域内的变量的使用方式,缺省是shared。

>OpenMP parallel

parallel制导指令用来创建并行域,后边要跟一个大括号将要并行执行的代码放在一起

#include<stdio.h>
#include<stdlib.h>
#include<omp.h>

void hello(void) {
    //返回线程号
	int my_rank = omp_get_thread_num();
    //返回当前并行区域中的线程数
	int thread_count = omp_get_num_threads();
	printf("Hello from thread %d of %d. \n", my_rank, thread_count);
}

int main(int argc, char** argv) {
	int thread_count = strtol(argv[1],NULL,10);
	
//num_threads指定要用多少个线程来实现hello
#pragma omp parallel num_threads(thread_count)
{
	hello();
}
	return 0;
}

在这里插入图片描述

>OpenMP for

#pragma omp parallel for它告诉编译器,接下来的for循环,将会使用并行的方式执行,使用并行的时候需要满足以下四个需求:

  • 在循环的迭代器必须是可计算的并且在执行前就需要确定迭代的次数;
  • 在循环的代码块中不能包含break,return,exit;
  • 在循环的代码块中不能使用goto跳出到循环外部;
  • 迭代器只能够被for语句中的增量表达式所修改。

数据依赖性:在该循环中的计算依赖于一个或更多个先前的迭代结果。当存在这种状况时,需要格外注意,容易出现错误。

#include<stdio.h>
#include<stdlib.h>
#include<omp.h>

int main(int argc, char** argv) {
	int thread_count = strtol(argv[1],NULL,10);
	double a[10], b[10];
	for (int i = 0; i < 10; i++) {
		a[i] = i;
		b[i] = 10 - i;
	}
	double s[10];
#pragma omp parallel for num_threads(thread_count)
	for (int i = 0; i < 10; i++){
		s[i] = a[i] + b[i];
		printf("线程编号%d: 结果%lf\n",omp_get_thread_num(), s[i]);
	}

	return 0;
}

在这里插入图片描述

>OpenMP private Variables

在OpenMP中,变量的作用域涉及在parallel块中能够访问该变量的线程集合。能够被线程组中所有线程访问的变量拥有共享作用域,而一个只能被单个线程访问的变量拥有私有作用域。

Private在#pragma中作为一个可选的,附加的选项,它能够直接的告诉编译器去使得共享变量作为每个线程中的私有变量。它的形式为 #pragma omp … private(< variable list >)

>>>private

关于private的信息:

  • 每一个线程都是拥有独自的该变量的副本;
  • 如果j被定义为私有变量,那么在for循环里面,所有的线程都不能访问其他j(尽管j是共享变量);
  • 所有的线程都不会使用到先前的定义;
  • 所有线程都不能给共享的j赋值;
#include<stdio.h>
#include<stdlib.h>
#include<omp.h>

int main(int argc, char** argv) {
	int thread_count = strtol(argv[1],NULL,10);
	double tmp = 1.0f;
#pragma omp parallel for num_threads(thread_count) private(tmp) 
	for (int i = 0; i < 10; i++)
	{
		tmp = 2.0f;
		printf("线程编号%d: 结果%lf\n", omp_get_thread_num(), tmp);
	}

	printf("tmp: %lf\n",tmp);

	return 0;
}

在这里插入图片描述

>>>firstprivate

关于firstprivate的信息:

  • firstprivate选项告诉编辑器私有变量在第一个循环会继承共享变量的值;
  • 这个私有的变量只会在每个线程的第一个循环继承,而不会在每个循环中继承;
  • 其使用方法于private几乎一致:#pragma omp parallel for firstprivate;

关于变量的拷贝:

  • 如果数据是基础数据类型,如int,double等,会将数据进行直接拷贝;
  • 如果变量是一个数组,它会拷贝一个对应的数据以及大小到私有内存中;
  • 如果变量为指针,它会将变量指向的地址拷贝过去,指向相同地址;
  • 如果变量是一个类的实例,它会调用对应的构造函数构造一个私有的变量。
#include<stdio.h>
#include<stdlib.h>
#include<omp.h>

int main(int argc, char** argv) {
	int thread_count = strtol(argv[1],NULL,10);
	int j = 4;
#pragma omp parallel for num_threads(thread_count) firstprivate(j) 
	for (int i = 0; i < 10; i++)
	{
		j++;
		int my_rank = omp_get_thread_num();
		int thread_count = omp_get_num_threads();
		printf("thread %d of %d has j = %d.\n", my_rank,thread_count,j);
	}

	printf("tmp: %d\n",j);

	return 0;
}

在这里插入图片描述

>>>lastprivate

关于lastprivate的信息:

  • lastprivate选项告诉编辑器私有变量会在最后一个循环出去的时候,用私有变量的值替换掉我们共享变量的值;
  • 当负责最后一个iteration的线程离开循环的时候,它会将该私有变量的值赋值给当前共享变量的值。
#include<stdio.h>
#include<stdlib.h>
#include<omp.h>

int main(int argc, char** argv) {
	int thread_count = strtol(argv[1],NULL,10);
	int j;
#pragma omp parallel for num_threads(thread_count) lastprivate(j) 
	for (int i = 0; i < 10; i++)
	{
		j = 4;
		j++;
		int my_rank = omp_get_thread_num();
		int thread_count = omp_get_num_threads();
		printf("thread %d of %d has j = %d.\n", my_rank,thread_count,j);
	}

	printf("tmp: %d\n",j);

	return 0;
}

在这里插入图片描述

>OpenMP section

sections在封闭代码的指定部分中,由线程组进行分配任务:

  • 每个独立的section都需要在sections里面;
  • 每个section可能执行不同的任务;
  • 如果一个线程够快,该线程可能执行多个section。
#include<stdio.h>
#include<stdlib.h>
#include<omp.h>

int main(int argc, char** argv) {
	int thread_count = strtol(argv[1],NULL,10);
#   pragma omp parallel num_threads(thread_count)
	{
#       pragma omp sections
	   {
#          pragma omp section
	       {
			   int my_rank = omp_get_thread_num();
			   int thread_count = omp_get_num_threads();
			   printf("thread %d of %d.\n", my_rank, thread_count);
	       }
#          pragma omp section
		   {
			   int my_rank = omp_get_thread_num();
			   int thread_count = omp_get_num_threads();
			   printf("thread %d of %d.\n", my_rank, thread_count);
		   }
#		   pragma omp section
		   {
			   int my_rank = omp_get_thread_num();
		   int thread_count = omp_get_num_threads();
		   printf("thread %d of %d.\n", my_rank, thread_count);
		   }
#		   pragma omp section
		   {
			   int my_rank = omp_get_thread_num();
		   int thread_count = omp_get_num_threads();
		   printf("thread %d of %d.\n", my_rank, thread_count);
		   }
	   }
	}
	return 0;
}

在这里插入图片描述

>>>reduction

reduction也是一种常见的子句,它为我们的parallel,for和sections提供了一个归并的功能:

  • 它会提供一个私有的变量拷贝并且初始化该私有变量;
  • 私有变量的初始化的值取决于选择的归并的操作符;
  • 这些变量的拷贝会在本地线程中进行更新;
  • 在最后的出口中,所有的变量拷贝将会通过操作符所定义的规则进行合并的计算,计算成一个共享变量;
  • 使用方法如下:#pragma omp … reduction(op:list)。

reduction提供的操作符几乎都是符合结合律的二元操作符,本地变量的初始值如下所示:

Operator Initial Value
+ 0
* 1
- 0
^ 0
& ~0
0
&& 1
丨丨 0
#include<stdio.h>
#include<stdlib.h>
#include<omp.h>

int main(int argc, char** argv) {
	int thread_count = strtol(argv[1],NULL,10);
	int j = 10;
	printf("j = %d\n", j);
#   pragma omp parallel num_threads(thread_count) reduction(+:j)
	{
#       pragma omp sections
	   {
#          pragma omp section
	       {
			   int my_rank = omp_get_thread_num();
			   int thread_count = omp_get_num_threads();
			   j = j + 10;
			   printf("Hello from thread %d of %d in section 1 and j = %d.\n", my_rank, thread_count,j);
	       }
#          pragma omp section
		   {
			   int my_rank = omp_get_thread_num();
			   int thread_count = omp_get_num_threads();
			   j = j + 20;
			   printf("Hello from thread %d of %d in section 2 and j = %d.\n", my_rank, thread_count, j);
		   }
	   }
	}

	printf("j = %d\n",j);
	return 0;
}

在这里插入图片描述

>OpenMP single

single选项是在并行块里面使用的:

  • 它告诉编译器接下来紧跟的下段代码将会只一个线程执行;
  • 它可能会在处理多段线程不安全代码时非常有用;
  • 在不使用no wait选项时,在线程组中不执行single的线程们将会等待single的结束
#pragma omp single nowait
{
   nthreads = omp_get_num_threads();
   printf("number of threads = %d\n",nthreads);
}

//与上面的代码大致等同
tid = omp_get_thread_num();
if(tid == 0){
   nthreads = omp_get_num_threads();
   printf("number of threads = %d\n",nthreads);
}

>OpenMP master

master选项是在并行块里面使用的:

  • 它告诉编译器接下来紧跟的下段代码将会会由主线程执行;
  • 它不会出现等待现象。
#pragma omp master
{
   nthreads = omp_get_num_threads();
   printf("number of threads = %d\n",nthreads);
}

//与上面的代码等同
tid = omp_get_thread_num();
if(tid == 0){
   nthreads = omp_get_num_threads();
   printf("number of threads = %d\n",nthreads);
}

>OpenMP barrier

在很多时候,需要线程之间团结协作完成某个任务,这就要求线程能够完成一致协调合作。OpenMP提供了多个操作,其中barrier和critical分别用于实现同步与互斥。

它是用于实现同步的一种手段,会在代码的某个点,令线程停下直到所有的线程都到达该地方。使用的语法如下:#pragma omp barrier。许多情况下,它已经能够自动的插入到工作区结尾,比如在for,single中,但是它能够被nowait禁用。

#include<stdio.h>
#include<stdlib.h>
#include<omp.h>

int main(int argc, char** argv) {
	int thread_count = strtol(argv[1],NULL,10);
	printf("使用barrier输出的结果:\n");
#   pragma omp parallel num_threads(thread_count)
	{
		int my_rank = omp_get_thread_num();
		int thread_count = omp_get_num_threads();
		printf("hi from %d\n", my_rank);
#       pragma omp barrier
		if (my_rank == 0) {
			printf("%d threads say hi\n", thread_count);
		}
	}
	printf("不使用barrier输出的结果:\n");
#   pragma omp parallel num_threads(thread_count)
	{
		int my_rank = omp_get_thread_num();
		int thread_count = omp_get_num_threads();
		printf("hi from %d\n", my_rank);
//#       pragma omp barrier
		if (my_rank == 0) {
			printf("%d threads say hi\n", thread_count);
		}
	}
	return 0;
}

在这里插入图片描述

>>>nowait

nowait在OpenMP中,用于打断自动添加的barrier的类型,如parallel中的for以及single,用法如下:#pragma omp for nowait 、#pragma omp single nowait。

#include<stdio.h>
#include<stdlib.h>
#include<omp.h>
#include<windows.h>

int main(int argc, char** argv) {
	int thread_count = strtol(argv[1],NULL,10);
	printf("使用nowait输出的结果:\n");
#   pragma omp parallel num_threads(thread_count)
	{
		int my_rank = omp_get_thread_num();
		int thread_count = omp_get_num_threads();
#       pragma omp for nowait
		for (int i = 0; i < 10; i++) {
			if (my_rank == 0)
				Sleep(3000);
			printf("Hello from thread %d of %d i = %d.\n", my_rank, thread_count, i);
		}
#       pragma omp single nowait
		{
			printf("thread %d process single\n", my_rank);
			Sleep(3000);
		}
		printf("thread %d ok\n", my_rank);
	}

	printf("不使用nowait输出的结果:\n");
#   pragma omp parallel num_threads(thread_count)
	{
		int my_rank = omp_get_thread_num();
		int thread_count = omp_get_num_threads();
#       pragma omp for
		for (int i = 0; i < 10; i++) {
			if (my_rank == 0)
				Sleep(3000);
			printf("Hello from thread %d of %d i = %d.\n", my_rank, thread_count, i);
		}
#       pragma omp single
			printf("thread %d process single\n", my_rank);
			Sleep(3000);
		printf("thread %d ok\n", my_rank);
	}
	return 0;
}

在这里插入图片描述

>OpenMP critical

竞争现象可以由下图表示:

在这里插入图片描述
OpenMP提供了一个实现互斥的接口:critical,它告诉编译器解析来的一段代码在同一个时间段将会只由一个线程进行,使用方法如下:#pragma omp critical。好处是解决了竞争现象;坏处是使用critical会让程序执行减少并行化程序,而且必须要写代码的人手动判断哪些部分需要用critical。

#include<stdio.h>
#include<stdlib.h>
#include<omp.h>

int main(int argc, char** argv) {
	int thread_count = strtol(argv[1],NULL,10);
	int j = 0;
#   pragma omp parallel for num_threads(thread_count) shared(j)
		for (int i = 0; i < 10; i++) {
			int my_rank = omp_get_thread_num();
			int thread_count = omp_get_num_threads();
#           pragma omp critical
			{
				j = j + 1;
				printf("Hello from thread %d of %d i = %d,j = %d\n", my_rank, thread_count, i, j);
			}
		}
	return 0;
}

在这里插入图片描述

>OpenMP atomic

在特殊的情况下,除了使用critical指令控制临界区以外,我们还可以使用其他选项去保证内存的控制是原子的,OpenMP提供了一个选项:atomic(原子),它只在特殊的情况下使用:在自增或自减的情况下使用;在二元操作数的情况下使用。并且其只会应用于一条指令。使用方法如下:#pragma omp atomic。

critical与atomic的区别如下图所示:
在这里插入图片描述

>OpenMP schedule

循环调度的种类:

  • 静态调度:在循环执行之前,就已经将循环任务分配好;
  • 动态调度:在循环执行过程中,边执行边分配。

OpenMP提供了一个指令schedule,它能够将循环分配给每个线程,当采用不同的参数时,我们会使用不同的调度方式。它的使用方式如下:shedule(static[,chunk]),当采用static的参数时,chunk代表了每一块分块的大小,它会采取转轮制度,谁先获取块,谁就能获得整一块的内容。特点是低开销,但是可能会造成分配的不均衡。具体理解如下图所示:

在这里插入图片描述
它的使用方式还有:shedule(dynamic[,chunk]),当采用dynamic的参数时,chunk代表了每一块分块的大小,每个线程执行完毕后,会自动获取下一个块,特点是高开销,但是能减少分配不均衡的情况。具体分配方式如下图所示:

它的使用方式还有:shedule(guide[,chunk]),当采用guide的参数时,会按照一定的规则分配块,这是一种动态的分配,每一块的分配数量是在不断收缩的,但是最小不会小于chunk。最初的块会被定义成:循环数量/线程数。其余块的大小会被定义成:剩余循环数量/线程数。具体分配方式如下图所示:

#include<omp.h>
#include<windows.h>
#include<time.h>

void delay() {
	int t = 50;
	int my_rank = omp_get_thread_num();
	t = t * (my_rank + 1);
	Sleep(t);
}

int main(int argc, char** argv) {
	int thread_count = strtol(argv[1],NULL,10);
	int j = 0;
	srand(time(NULL));
	clock_t start, end;
	start = clock();
#   pragma omp parallel for num_threads(thread_count) schedule(static,2)
		for (int i = 0; i < 100; i++) {
			delay();
		}
	end = clock();
	printf("first loop finish,time: %f\n", (double)end - start);

	start = clock();
#   pragma omp parallel for num_threads(thread_count) schedule(dynamic,2)
	for (int i = 0; i < 100; i++) {
		delay();
	}
	end = clock();
	printf("second loop finish,time: %f\n", (double)end - start);

	start = clock();
#   pragma omp parallel for num_threads(thread_count) schedule(guided,2)
	for (int i = 0; i < 100; i++) {
		delay();
	}
	end = clock();
	printf("third loop finish,time: %f\n", (double)end - start);
	return 0;
}

在这里插入图片描述

4.环境变量

OpenMP中定义一些环境变量,可以通过这些环境变量控制OpenMP程序的行为,常用的环境变量如下:

  • OMP_SCHEDULE:用于for循环并行化后的调度,它的值就是循环调度的类型;
  • OMP_NUM_THREADS:用于设置并行域中的线程数;
  • OMP_DYNAMIC:通过设定变量值,来确定是否允许动态设定并行域内的线程数;
  • OMP_NESTED:指出是否可以并行嵌套。

5.API函数

函数名 函数作用
omp_in_parallel 判断当前是否在并行域中
omp_get_thread_num 返回线程号
omp_set_num_threads 设置后续并行域中的线程格式
omp_get_num_threads 返回当前并行区域中的线程数
omp_get_max_threads 获取并行域可用的最大线程数目
omp_get_num_procs 返回系统中处理器的个数
omp_get_dynamic 判断是否支持动态改变线程数目
omp_set_dynamic 启用或关闭线程数目的动态改变
omp_get_nested 判断系统是否支持并行嵌套
omp_set_nested 启用或关闭并行嵌套
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenMP并行编程 的相关文章

  • 如何正确生成/恢复 OpenMP 未绑定任务?

    我编写了一个小型 C 程序来评估 OpenMP 在任务出现空闲时间 例如等待通信数据 时让出另一个任务的能力 include
  • 使用一个线程执行一个部分,并使用多个线程执行一个 for 循环

    我正在使用 OpenMP 并且想要生成线程 以便一个线程执行一段代码并完成 与运行并行 for 循环迭代的 N 个线程并行 执行应该是这样的 Section A one thread Section B parallel for multi
  • OpenMp 与 IOS/Android 的兼容性

    我正在尝试做什么 我正在研究C c 为所有平台构建产品的代码 我操作系统 Android Windows 移动 桌面 Mac Linux 到目前为止我做了什么 是的 有许多在线链接讨论 OpenMp 与不同处理器和操作系统的兼容性 但很难从
  • JUC的常见类

    目录 Callable ReentrantLock Semaphore CountDownLatch JUC 即 java util concurrent 其中存放了一些进行多线程编程时有用的类 Callable Callable是一个接口
  • 使用 OpenMP 的程序崩溃,仅限 x64

    当我在 Release x64 中构建下面的程序时 它会崩溃 所有其他配置都运行良好 是我做错了还是 OpenMP 问题 扎实的解决方法受到高度赞赏 要使用以下代码重现构建项目 控制台应用程序 在 Release x64 配置中使用 ope
  • osx 和 clion,找不到 omp.h

    如何说服 cmake 在 CLion 内 我有可用的 OpenMP 标头 我正在尝试编译这个项目SCD https github com DAMA UPC SCD我收到以下错误 15 Building CXX object tools se
  • 关闭 OpenMP

    在我的 C 程序中 我希望有时使用 OpenMP 有时不使用 OpenMP 即多线程或单线程 来运行其可执行文件 我正在考虑以下两种情况中的任何一种 我的代码如何使用 OpenMP 1 假设我的代码只有 include
  • Xcode C++ omp.h 文件未找到

    我正在尝试将 openmp 包含到我的 Xcode C 项目中 我已将 Xcode 中的编译器更改为 LLVM GCC 4 2 添加 fopenmp 作为 CFlag 并在 xcode 中启用了 OpenMP 支持 但它仍然显示 omp h
  • OpenMP 中使用循环的并行部分

    我想知道是否有任何技术可以使用 for 循环在 OpenMp 中创建并行部分 例如 我不想创建 n 个不同的 pragma omp 部分 而是使用 n 次迭代来创建它们for loop每个部分都有一些变化的参数 pragma omp par
  • 通过迭代自适应阈值和形状分析检测圆形物体簇

    我一直在开发一个应用程序来计算圆形物体 例如图片中的细菌菌落 让这一切变得简单的是 物体通常与背景有很大区别 然而 有一些困难使得分析变得棘手 背景将呈现渐变以及快速的强度变化 在容器的边缘 对象将是椭圆形而不是圆形 物体的边缘有时相当模糊
  • 时间:2019-03-07 标签:c++openmp和threadprivate

    我遇到的情况是 在一台计算机 具有高性能节点的集群 上有一个代码 可以编译 但在我的个人电脑上却不能 错误是 var declared threadprivate after first use pragma omp threadpriva
  • c openmp并行用于并行区域内

    我的问题是这样的one https stackoverflow com questions 11493265 for loop inside parallel region 但我想做一些不同的事情 例如 在我的并行区域内 我想在 4 个线程
  • Qt 支持 OpenMP 吗?

    我在 Visual Studio 项目中使用 OpenMP 目前非常认真地考虑更改为 QT Creator Visual Studio 不是很糟糕吗 我对微软的期望更高 但无论如何 QT Creator 支持 OpenMP 吗 如果出现这种
  • Android OpenCV 并行化循环

    我知道 OpenMP 包含在 NDK 中 使用示例如下 http recursify com blog 2013 08 09 openmp on android http recursify com blog 2013 08 09 open
  • 在不平衡树上拆分 OpenMP 线程

    我正在尝试使用 OpenMP 并行进行树操作 例如对树中所有叶子中的数字进行求和 我遇到的问题是我工作的树不平衡 子节点的数量不同 分支的大小也不同 我目前在这些树上使用递归函数 我想要实现的是 1 在第一个可能的机会时分割线程 假设它是一
  • Eigen 和 OpenMP:由于错误共享和线程开销而没有并行化

    系统规格 Intel Xeon E7 v3 处理器 4 插槽 16 核 插槽 2 线程 核心 Eigen 系列和 C 的使用 以下是代码片段的串行实现 Eigen VectorXd get Row const int j const int
  • 具有主区域的 OpenMP for 循环:“主区域可能不会紧密嵌套在工作共享或显式任务区域内”

    我有以下代码 我相信它应该显示一个进度条 近似整个过程的进度 因为循环的每个并行线程应该以大约相同的速率进行 pragma omp parallel for for long int x 0 x
  • 在 omp 并行 for 循环中使用 unique_ptr 会导致 SEG.FAULT

    采取以下代码 include
  • c++ OpenMP 关键:“单向”锁定?

    考虑以下串行函数 当我并行化代码时 每个线程都会从并行区域内调用此函数 未显示 我正在尝试使这个线程安全and高效 快速 float get stored value or calculate if does not yet exist i
  • 如何使用 OpenMP 并行化数组移位?

    如何使用 OpenMP 并行化数组移位 我已经尝试了一些方法 但没有得到以下示例的任何准确结果 该示例旋转 Carteira 对象数组的元素 用于排列算法 void rotaciona int i Carteira aux this gt

随机推荐

  • 数据库设计(真题讲解)-软件设计(三十四)

    系统开发 McCabe复杂度 下 软件设计 三十三 https blog csdn net ke1ying article details 129719533 spm 1001 2014 3001 5501 ER模型 1对1 1对多 多对多
  • matlab相关性分析频谱_利用Matlab绘制正弦信号的频谱图并做相关分析范文

    专业知识整理分享 利用 Matlab 绘制正弦信号的频谱图并做相关分析 一 作业要求 1 信号可变 信号的赋值 相位 频率可变 2 采样频率 fs 可变 3 加各种不同的窗函数并分析其影响 4 频谱校正 5 频谱细化 二 采用 matlab
  • 最少砝码问题(用一部分数的和/差表示区间上所有的整数)

    问题1 需要表示 1 N 的所有重量 最少需要多少砝码 答案 需要 1 2 4 ceiling logN 每个砝码代表二进制数的一位 N有ceiling logN 个二进制位 问题2 需要表示 1 N 的所有重量 手头已有一些砝码 问 怎样
  • 微信小程序获取用户手机号

    微信小程序获取用户手机号需要企业小程序 个人小程序是无法获取到手机号的 我们先看看官方的解释 获取手机号 获取微信用户绑定的手机号 需先调用wx login接口 因为需要用户主动触发才能发起获取手机号接口 所以该功能不由 API 来调用 需
  • mysql脏读,幻读,不可重复读以及间隙所解决幻读

    1 数据脏读 事务a修改了某条数据 然后事务b读取了事务a修改的该条数据 然后事务a由于某些原因 事务a回滚了 这样事务b读到的数据就和回滚的数据不同了 这时事务b读取的数据就是脏数据 概况一句话就是一个事务读取了另一个事务未提交的数据 2
  • 免费看小说,国产浏览器出手了,吊打各类阅读软件

    一 UC浏览器 小说多且免费 UC浏览器提供了非常方便的小说阅读体验 用户可以随意选择自己想要阅读的小说网站 并且一键切换到纯净的阅读模式 享受真正的沉浸式阅读 此外 UC浏览器还自带书城 用户可以在这里找到各种受欢迎的小说 避免书荒 书城
  • webpack-dev-server配合nginx启动时遇到热替换模块请求跨域

    当本地URL已经用Nginx代理 例如http vue native guahao inc 代理到http vue native guahao inc com不带端口号时 本地的webpack dev server会遇到请求热更新的json
  • android.accounts包

    包 android accounts 英文原文 http developer android com reference android accounts package summary html 版本 Android 4 0 r1 译者署
  • 概率论与数理统计

    概率论与数理统计 一 概率论基本概述 1 1 随机试验 1 2 样本空间与随机事件 1 3 频率与概率 1 4 古典概型 1 5 条件概率 1 6 独立性 二 随机变量及其分布 2 1 随机变量 2 2 离散型随机变量及其分布 2 3 随机
  • mbed OS会成为物联网的 Android 吗?

    转载至 http www mbed org cn archives mbed os E4 BC 9A E6 88 90 E4 B8 BA E7 89 A9 E8 81 94 E7 BD 91 E7 9A 84 android E5 90 9
  • 使用远程服务器总是因网络中断、终端不小心关闭、锁屏等导致程序中断

    分享编程工具实用方法 面对无穷无尽的配置bug 其他文章 Windows连接远程Linux服务器 VSCode配置 免密设置 跳板机配置 GeForce RTX 3090无法使用mmsegmentation官方推荐cuda版本 ubuntu
  • 计算机辅助实验圆弧连接画法,机械制图基础-18、圆弧连接的画法

    绘图时 经常要用已知半径的圆弧 但圆心要在作图中确定 这样的圆弧 称为连接圆弧 连接圆弧需要光滑连接已知直线或圆弧 光滑连接也就是要在连接点处相切 为了保证相切 必须准确地作出连接圆弧的圆心和切点 一 用已知半径为R的圆弧连接两条已知直线
  • 超七成阅读APP都借百度语音技术促用户增长

    全国十多亿人在这个春节集体 关门闭户 与手机和网络作伴 除了手游和短视频流量飞涨 在线阅读也迎来 高光时刻 特别是当手机阅读APP标配了语音朗读即 听书 功能 据百度大脑AI开放平台的后台数据显示 疫情期间 支持 听书 功能的语音合成技术的
  • 重新映射图像——OpenCV Remap实例

    重新映射图像 OpenCV Remap实例 在计算机视觉领域中 图像的几何变换是一项重要的工作 重要的任务之一是将图像转换为其他形式 例如投影或扭曲 OpenCV的Remap函数提供了一个简单和灵活的方法来执行这种类型的变换 下面展示了如何
  • unsigned char 数值溢出问题

    include
  • 在D盘使用SVN检出文件后,整个盘出现蓝色问号的解决办法。

    在D盘使用SVN检出文件后 整个盘出现蓝色问号的解决办法 原因 在该盘的根目录执行了checkout操作 SVN将整个盘作为了一个版本库的本地副本 那些问号表示这些文件没有被SVN控制 解决方法 1 在文件上右击 选择TortoiseSVN
  • android studio电影院选座,8排电影院选座最佳位置

    8排电影院选座最佳位置在哪里呢 8排电影院属于小影厅 小影厅银幕宽度在10米以下 座位100以内 座位排数通常拥有8 14排 小影厅整体空间小 选座时要选中间稍靠后一些的位置 由于整体排数少 因此选即便选择靠后一些的排数实际上距银幕的距离也
  • ubuntu 同时使用无线网卡和有线网卡

    转载于这位博主 文章
  • Ubuntu18.04 取消开机密码 实现自动登录

    因为要把Ubuntu设备作为服务器 实现开机自动运行服务程序 所以需要取消开机密码 实现自动登录 1 点击桌面右上角向下的箭头 点击设置图标 2 点击右上角的 Unlock 3 在弹出的窗口中输入系统登录密码 点击右下角 Authentic
  • OpenMP并行编程

    1 总览 OpenMP Open Multi Processing 是一种用于共享内存并行系统的多线程程序设计方案 支持的编程语言包括C C 和Fortran OpenMP提供了对并行算法的高层抽象描述 通过线程实现并行化 特别适合在多核C