【数据结构与算法】并行搜索
像以前只有一个CPU的时候,要想处理多个软件时,只能通过时间片,来处理,就是这个CPU一会处理这个软件,一会处理那个软件,只不过速度太快,我们没有反应过来,以为是同时进行的.一个进程也就是一个软件,同时也有着多个线程,每个线程可以独立并行执行,多个线程共享同一进程资源,受进程管理.就是进程和线程是同时进行的,加了这个进程会等待线程完成才进行往下走.线程是同时进行的,所以完成搜索只用了6秒,刚刚普通
大家好,这里是国中之林!
❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看←
一.并行的基础知识
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
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)