大家好,这里是国中之林!
❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看←

一.并行的基础知识

1.进程

说的简单点,进程就是计算机中的多个程序,就相当于多个软件.
比如我同时打开QQ和WX,那么这个就叫做并发.
像现在的计算机一般都是多CUP.
可以并发处理程序,速度非常快.
像以前只有一个CPU的时候,要想处理多个软件时,只能通过时间片,来处理,就是这个CPU一会处理这个软件,一会处理那个软件,只不过速度太快,我们没有反应过来,以为是同时进行的.

2.线程

一个进程也就是一个软件,同时也有着多个线程,每个线程可以独立并行执行,多个线程共享同一进程资源,受进程管理.
那么并行搜索就是在此基础上实现的.

二.正常遍历搜索

咱们定义这个大数组,在里面找NUMBER这个值.
在这里插入图片描述
因为搜索太快了,都不到1秒,所以我又重新遍历了50遍.

int main()
{
	int* data = NULL;
	int count = 0;//记录的数量
	data = new int[TEST_SIZE];
	
	for (int i = 0; i < TEST_SIZE; i++)
	{
		data[i] = i;
	}
	
	time_t start=0, end=0;//记录开始和结束的时间搓
	time(&start);
	for (int j = 0; j < 50; j++)
	{
		for (int i = 0; i < TEST_SIZE; i++)
		{
			if (data[i] == NUMBER)
			{
				count++;
			}
		}
	}
	time(&end);
	printf("查找所花的时间:%lld\n", end - start);

	system("pause");
	return 0;
}

运行结果:
在这里插入图片描述

三.线程并发搜索

我们现在来创建两个线程来帮我们打工,数组分成两部分同时进行遍历.

1.线程身份证和句柄

每个线程都有自己的ID.
在这里插入图片描述

2.创建线程

CreateThread函数返回的是HANDLE.
创建线程的目的就是要去处理某些事情,那么在程序中就是函数.
ThreadProc是我们要处理的自定义函数.
&s1就是自定义处理函数的参数
最后一个参数就是是那个线程.
在这里插入图片描述

3.搜索结构体

我们将搜索范围定义成了结构体.
在这里插入图片描述
将两部分位置初始化给search结构体.
在这里插入图片描述

4.处理函数实现

线程的函数,我圈的地方是固定的.
void*需要强制类型才能使用.
在这里插入图片描述
运行结果:
在这里插入图片描述
线程是同时进行的,所以完成搜索只用了6秒,刚刚普通的是用了9秒.

四.完整代码

#include <Windows.h>
#include <stdio.h>
#include <iostream>
#include <time.h>

#define TEST_SIZE (1024*1024*200)
#define NUMBER 20

typedef struct _search
{
	int* data;//搜索的数据集
	size_t start;//搜索的开始位置
	size_t end;//搜索的终止位置
	size_t count;//搜索的结结果
}search;

DWORD WINAPI ThreadProc(void* lpParam)
{
	search* s = (search*)lpParam;
	time_t start, end;
	printf("新的线程开始了...\n");
	time(&start);
	for (int j = 0; j < 50; j++)
	{
		for (size_t i = s->start; i < s->end; i++)
		{
			if (s->data[i] == NUMBER)
			{
				s->count++;
			}
		}
	}
	time(&end);
	printf("查找所花的时间:%lld\n", end - start);

	return 0;
}

int main()
{
	int* data = NULL;
	int count = 0;
	int mid = 0;
	search s1, s2;
	data = new int[TEST_SIZE];
	for (int i = 0; i < TEST_SIZE; i++)
	{
		data[i] = i;
	}
	mid = TEST_SIZE / 2;
	s1.data = data;
	s1.start = 0;
	s1.end = mid;
	s1.count = 0;

	s2.data = data;
	s2.start = mid + 1;
	s2.end = TEST_SIZE - 1;
	s2.count = 0;


	DWORD threadID1;//线程1的身份证
	HANDLE hThread1;//线程1的句柄

	DWORD threadID2;//线程2的身份证
	HANDLE hThread2;//线程2的句柄

	printf("创建线程......\n");
	//创建线程1
	hThread1 = CreateThread(NULL, 0, ThreadProc, &s1, 0, &threadID1);

	//创建线程2
	hThread2 = CreateThread(NULL, 0, ThreadProc, &s2, 0, &threadID2);

	WaitForSingleObject(hThread1, INFINITE);
	WaitForSingleObject(hThread2, INFINITE);

	printf("线程完毕!count:%d\n",s1.count+s2.count);
	system("pause");
	return 0;
}


int main1()
{
	int* data = NULL;
	int count = 0;//记录的数量
	data = new int[TEST_SIZE];
	
	for (int i = 0; i < TEST_SIZE; i++)
	{
		data[i] = i;
	}
	
	time_t start=0, end=0;//记录开始和结束的时间搓
	time(&start);
	for (int j = 0; j < 50; j++)
	{
		for (int i = 0; i < TEST_SIZE; i++)
		{
			if (data[i] == NUMBER)
			{
				count++;
			}
		}
	}
	time(&end);
	printf("查找所花的时间:%lld\n", end - start);

	system("pause");
	return 0;
}

这个是等待线程的结束,INFINITE是一直等待,int类型的最大值.
不加这个的话,main函数会先执行完.
就是进程和线程是同时进行的,加了这个进程会等待线程完成才进行往下走.
在这里插入图片描述

2024年8月21日11:28:29

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐