研究遗传算法的一大诟病就是每次运行程序的结果并不是完全一样的,有时候能找到最优解有时候找不到最优解,这就是遗传算法的概率性导致的。那么怎么评价你的方法的好坏呐,这时候就要多次独立运行程序最后取结果的平均值或者计算算法的运行成功率。那么问题就来了,遗传算法的运行时间本来就略长,尤其当测试数据集很大且数量很多的时候,做一次实验跑完所有数据的时间有时候有点让人难以接受。于是想到了使用多线程,这样就可以同时运行多组独立的实验,最后再整合所有子线程的输出数据,计算运行成功率或者取最优解的平均值即可,怀揣着这个想法,开始尝试着用多线程编程来加快实验进度。以下是这几天的学习、实验过程和结果。

本人一直用Windows下的VS 2010编程,看了很多关于多线程编程的博客和资料之后我决定不用win32的API来实现多线程(各种函数名太长看着都懒得搞),而使用pthread的windows开发包(下载地址http://sourceware.org/pthreads-win32/下载任意版本,本人下载的是最新版pthreads-w32-2-9-1-release.zip,在VS下的配置方法稍后描述)比较方便。So, 多线程编程即将搞起来~~~

第一步:在VS2010下配置pthread
下载好pthread之后解压到任意文件夹,解压之后包含三个文件夹 Pre-built.2 pthreads.2 以及QueueUserAPCEx。在配置中需要用到的只有第一个文件夹下的东西。打开Pre-built.2文件夹会开到三个文件夹分别是dll、include、lib以及一对其他文件,从这三个文件夹就可以看出接下来要怎么配置。

1.将include路径填加为VS的包含路径。 例如我的include路径是F:\C&C++\多线程编程\pthreads-w32-2-9-1-release\Pre-built.2\include。填加该路径至包含路径

打开 属性管理器->右击->属性->VC++目录->包含目录, 将要填加的目录复制粘贴进去点击确定(主意千万不要在路径前面填加“$”符号,否则出错)

2.填加库目录。同第一步,将lib文件夹的目录填加进库目录

3.填加lib文件到附加依赖项。属性管理器->右击->属性->链接器->输入->附加依赖项。将lib文件夹下的.lib文件文件名复制粘贴在该项目下,记得每一个lib文件名换行。

4.将dll文件夹下的dll文件复制粘贴到你的VS项目根目录下。就可以开始使用pthread在VS中写多线程程序了。

第二步.编程

下面是我的程序

#include"rcpsp.h"//自己编写的头文件
#include<pthread.h>//pthread头文件,多线程的东西都在里面
//===========10个线程=========================
//每个线程是一次独立的实验,每组数据十次独立运行,所以编写十个子线程,以求快速完成实验
void* process_0(void *arg);
void* process_1(void *arg);
void* process_2(void *arg);
void* process_3(void *arg);
void* process_4(void *arg);
void* process_5(void *arg);
void* process_6(void *arg);
void* process_7(void *arg);
void* process_8(void *arg);
void* process_9(void *arg);
//==========================================
typedef struct
{
//===========Input Variables============
....
//===========Output Variables===========
.... }InputData; int main(void)
{
pthread_t p0,p1,p2,p3,p4,p5,p6,p7,p8,p9;//定义pthread变量
InputData Data[10]; //子线程输入输出数据
//=================multi threads========================= pthread_create(&p0,NULL,process_0,(void*)&Data[0]);
pthread_create(&p1,NULL,process_1,(void*)&Data[1]);
pthread_create(&p2,NULL,process_2,(void*)&Data[2]);
pthread_create(&p3,NULL,process_3,(void*)&Data[3]);
pthread_create(&p4,NULL,process_4,(void*)&Data[4]);
pthread_create(&p5,NULL,process_5,(void*)&Data[5]);
pthread_create(&p6,NULL,process_6,(void*)&Data[6]);
pthread_create(&p7,NULL,process_7,(void*)&Data[7]);
pthread_create(&p8,NULL,process_8,(void*)&Data[8]);
pthread_create(&p9,NULL,process_9,(void*)&Data[9]); pthread_join(p0,NULL);
pthread_join(p1,NULL);
pthread_join(p2,NULL);
pthread_join(p3,NULL);
pthread_join(p4,NULL);
pthread_join(p5,NULL);
pthread_join(p6,NULL);
pthread_join(p7,NULL);
pthread_join(p8,NULL);
pthread_join(p9,NULL);
//==================输出数据后处理========================
....
}

以上是我主程序的大概流程,由于pthread_create()创建子线程的时候给子线程函数的传入参数只有一个,所以当你需要给子函数传递多个函数参数或者需要传出参数的时候只能定义一个结构体,将所有输入和输出数据全部包装在结构体中,然后将结构体变量的引用传入子线程函数即可。在本例中,将所有输入输出参数全部包装在结构体InputData中,由于有十个子线程,为了避免不必要的麻烦,所以定义十个变量,用来输入和输出函数参数和返回值。

关于pthread_join( , )函数,它有两个参数,具体含义可以查阅其他博文。其作用是让主线程等待子线程结束,整个main函数是主线程,如果没有pthread_join这句代码,当主线程结束的时候,所有子线程也会被终止,而不管子线程是否已经结束,而大多数情况下,主线程会很快结束,然后创建的子线程还没有执行就随着主线程的结束而结束,所以一定要加一句等待子线程结束的代码。当然还有更简便的函数pthread_exit(),也可在所有线程的最后写上phread_exit(0)来让主线程等待所有子线程的结束。

phread.h中包含很多函数,在这里就不一一介绍,具体可参阅https://sourceware.org/pthreads-win32/manual/index.html

关于创建多少个线程才能效率更好的问题,网上和书上大部分推荐创建的线程数为CPU核数N 的2倍或者2*N+2个。所以这多线程和硬件关系特别大,如果是单核处理器,那完全不建议使用多线程,不然不但不会提高运行效率,反而线程之间的切换会占去很大一部分开销。

那么,我的实验运行速度提高了多少呐?? 答案是:没有提高。

让两台机子分别跑同一个数据集,一个采用上面的多线程方法,另一个串行执行每一组实验,经过对比,很悲伤的发现,串行的实验组跑得更快,当然和遗传算法本身也有很大的关系,每次一初始化不同,变异、交叉概率不同导致的找到解的时间就会不同,但是,这样的结果也是够让我伤心的了,搞了两天的多线程编程,查阅各种博客、去图书馆查资料,改程序,调程序,结果~~效果并不理想,也许是我的实验方法有问题,亦或是我的程序有问题,反正,多线程并没有加快我的实验进度。但是以后还是会尝试用多线程或者并行编程来加快遗传算法的实验速度的。

pthread Win32多线程编程的一些知识和感想的更多相关文章

  1. ZT 为什么pthread_cond_t要和pthread_mutex_t同时使用 || pthread/Linux多线程编程

    为什么线程同步的时候pthread_cond_t要和pthread_mutex_t同时使用 (2009-10-27 11:07:23) 转载▼ 标签: 杂谈 分类: 计算机 举一个例子(http:// ...

  2. Win32多线程编程(1) — 基础概念篇

      内核对象的基本概念 Windows系统是非开源的,它提供给我们的接口是用户模式的,即User-Mode API.当我们调用某个API时,需要从用户模式切换到内核模式的I/O System Serv ...

  3. Win32多线程编程(2) — 线程控制

    Win32线程控制只有是围绕线程这一内核对象的创建.挂起.恢复.终结以及通信等操作,这些操作都依赖于Win32操作系统提供的一组API和具体编译器的C运行时库函数.本篇围绕这些操作接口介绍在Windo ...

  4. Win32多线程编程(3) — 线程同步与通信

      一.线程间数据通信 系统从进程的地址空间中分配内存给线程栈使用.新线程与创建它的线程在相同的进程上下文中运行.因此,新线程可以访问进程内核对象的所有句柄.进程中的所有内存以及同一个进程中其他所有线 ...

  5. win32多线程编程

    关于多线程多进程的学习,有没有好的书籍我接触的书里头关于多线程多进程部分,一是<操作系统原理>里面讲的相关概念   一个是<linux基础教程>里面讲的很简单的多线程多进程编程 ...

  6. 多线程学习:win32多线程编程基本概念(转)

    一.定义: 1.进程和线程的区别 进程:是程序的执行过程,具有动态性,即运行的程序就叫进程,不运行就叫程序 ,每个进程包含一到多个线程.线程:系统中的最小执行单元,同一进程中有多个线程,线程可以共享资 ...

  7. 《Java多线程编程核心技术》知识梳理

    <Java多线程编程核心技术> @author ergwang https://www.cnblogs.com/ergwang/ 文章末尾附pdf和png下载链接 第1章 Java多线程技 ...

  8. .NET多线程编程(转)

    在.NET多线程编程这个系列我们讲一起来探讨多线程编程的各个方面.首先我将在本篇文章的开始向大家介绍多线程的有关概念以及多线程编程的基础知识;在接下来的文章中,我将逐一讲述.NET平台上多线程编程的知 ...

  9. [转]Delphi多线程编程入门(一)

    最近Ken在比较系统地学习Delphi多线程编程方面的知识,在网络上查阅了很多资料.现在Ken将对这些资料进行整理和修改,以便收藏和分享.内容基本上是复制粘贴,拼拼凑凑,再加上一些修改而来.各个素材的 ...

随机推荐

  1. 定时任务 bash 对远程数据库 备份 读写

    1g表 每行都有可能被更新,故全表备份 检测备份是否在进行 [root@hadoop1 ~]# netstat --numeric-ports | grep 3306tcp        0      ...

  2. 20170111 ABAP技术小结(全半角转换)

    DATA: it_po LIKE it_alv OCCURS 0 WITH HEADER LINE.************************************************** ...

  3. Genymotion设置网络桥接

    1,打开Genymotion,找到对应的模拟器,点击“设置”按钮 2,在网络选项中选择桥接 Bridge

  4. Chapter 20: Diagnostics

    WHAT'S IN THIS CHAPTER?n Code contractsn Tracingn Event loggingn Performance monitoringWROX.COM CODE ...

  5. usdt源码编译安装

    1.依赖关系Boost >= 1.53 2.安装依赖包You will need appropriate libraries to run Omni Core on Unix, please s ...

  6. bzoj4276

    线段树优化建图+费用流 朴素的做法是每个强盗直接对每个区间的每个点连边,然后跑最大权匹配,这样有5000*5000条边,肯定过不去,那么我们用线段树优化一下,因为线段树能把一个O(n)的区间划分为O( ...

  7. mysql 数据库的名称不能以数字开头

    mysql  数据库的名称不能以数字开头

  8. 关于使用jxl去读写Excel文件

    1.引入maven依赖 <dependency> <groupId>net.sourceforge.jexcelapi</groupId> <artifact ...

  9. 使用oracle的保留字作为字段名称并进行操作的方法

    项目中调取业主的数据库时发现,其中一个表的一个字段名为:update,所以当我用数据库查询语句进行查询的时候总会出错.从网上查询之后发现原来很简单,只要把update加上双引号就好了,例如: sele ...

  10. Linux下安装Redis及搭建主从

    Linux下安装Redis 首先在官网下载对应版本的redis包,这里本人使用的是redis-4.0.8.tar.gz.   然后在服务器中存放redis包的路径下执行tar –vxf redis-4 ...