如何通过循环将OpenMP线程拆分为子团队

时间:2016-01-09 01:07:26

标签: c++ c multithreading parallel-processing openmp

假设我有一个以下在内部使用public partial class Form1 : Form { SqlConnection sharedSqlConnection; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { //Defining all Parent Tree Nodes TreeNode AcctParentNode; TreeNode CompParentNode; TreeNode ServerParentNode; TreeNode TechParentNode; //Establish Shared Sql Connection sharedSqlConnection = new SqlConnection(); sharedSqlConnection.ConnectionString = @"Data Source=DevOps-CTD-Prim.devops.lab;Initial Catalog=Registry; User ID=sa;Password=************"; try { //We use the Open() method to establish the connection sharedSqlConnection.Open(); } catch (SqlException ex) { MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); Application.ExitThread(); } //Declaring All Parent Tree Nodes AcctParentNode = trvAccountList.Nodes.Add("List All Accounts"); CompParentNode = trvCompList.Nodes.Add("List All Computers"); ServerParentNode = trvServerList.Nodes.Add("List All Servers"); TechParentNode = trvTechList.Nodes.Add("List All Technicians"); //Add Dummy Node AcctParentNode.Nodes.Add("*"); CompParentNode.Nodes.Add("*"); ServerParentNode.Nodes.Add("*"); TechParentNode.Nodes.Add("*"); } private void trvAccountList_AfterSelect(object sender, TreeViewEventArgs e) { TreeNode nodeSelected, nodeChild; nodeSelected = e.Node; string strSQL = "Select * from Customer Order by Account"; SqlCommand populateAccountTree = new SqlCommand(); populateAccountTree.Connection = sharedSqlConnection; populateAccountTree.CommandText = strSQL; ***if (nodeSelected.Nodes[0].Text == "*")*** { //This is a dummy node. nodeSelected.Nodes.Clear(); SqlDataReader accountType = populateAccountTree.ExecuteReader(); while (accountType.Read()) { nodeChild = nodeSelected.Nodes.Add(accountType["Account"].ToString()); nodeChild.Tag = accountType["LastName"]; } } } 的函数。

#pragma omp parallel

我现在想要void do_heavy_work(double * input_array); do_heavy_work因此:

input_arrays

假设我有void do_many_heavy_work(double ** input_arrays, int num_arrays) { for (int i = 0; i < num_arrays; ++i) { do_heavy_work(input_arrays[i]); } } 个硬件线程。上面的实现将导致N num_arrays的调用以串行方式发生,每个调用都在内部使用所有do_heavy_work线程来执行它想要的任何并行操作。

现在假设在N时,在这个外部循环上并行化比在num_arrays > 1内部并行化更有效。我现在有以下选择。

  • do_heavy_work放在外部循环上并设置#pragma omp parallel for。但是,通过设置OMP_NESTED=1,最终会产生大量的线程(OMP_NUM_THREADS=N)。
  • 如上所述,但关闭嵌套并行性。这会在N*num_arrays
  • 时浪费可用内核

理想情况下,我希望OpenMP将其num_arrays < N个线程团队拆分为OMP_NUM_THREADS个子团队,然后每个num_arrays可以通过其分配的子团队进行线程化。

实现这一目标的最简单方法是什么?

(出于本次讨论的目的,我们假设do_heavy_work不一定事先知道,而且我也无法更改num_arrays本身的代码。代码应该适用于多台机器所以do_heavy_work应该是可以自由指定的。)

1 个答案:

答案 0 :(得分:3)

//remove "Home","Work" from list.remove("Home") list.remove("Work") Collections.sort(list) //order of the following two matters list.add(0, "Work") list.add(0, "Home") 可以设置为列表,从而指定每个嵌套级别的线程数。例如。 OMP_NUM_THREADS将告诉OpenMP运行时执行具有10个线程的外部并行区域,每个嵌套区域将使用4个线程执行,总共最多40个同时运行的线程。

或者,您可以使用与此类似的代码使您的程序自适应:

OMP_NUM_THREADS=10,4

如果void do_many_heavy_work(double ** input_arrays, int num_arrays) { #pragma omp parallel num_threads(num_arrays) { int nested_team_size = omp_get_max_threads() / num_arrays; omp_set_num_threads(nested_team_size); #pragma omp for for (int i = 0; i < num_arrays; ++i) { do_heavy_work(input_arrays[i]); } } } 的值不能被OMP_NUM_THREADS整除,则此代码不会使用所有可用线程。如果每个嵌套区域具有不同数量的线程(可能导致某些阵列的处理速度比其他阵列快),请想出如何分配线程并相应地在每个线程中设置num_arrays。从并行区域内调用nested_team_size仅影响由调用线程启动的嵌套区域,因此您可以拥有不同的嵌套团队大小。