实验二 编写Pthreads程序实现“任务队列”

该程序创建一个Pthreads任务队列,由主线程生成任务并唤醒等待的线程执行。每个线程执行完任务后重新进入等待状态。任务通过链表管理,主线程生成所有任务后广播唤醒所有线程,利用条件变量和互斥锁保证同步。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

编写一个Pthreads程序实现一个“任务队列”。主线程启动用户指定数量的线程,这些线程进入条件等待状态。主线程生成一些任务(一定计算量),每生成一个新的任务,就用条件变量唤醒一个线程,当这个唤醒线程执行完任务时,回到条件等待状态。当主线程生成完所有任务,设置全局变量表示再没有要生成的任务了,并用一个广播唤醒所有线程。为了清晰起见,建议任务采用链表操作

可以自己手动改 Gen_work函数中的循环次数以改变任务计算量

计时头文件

不想看运行时间也可以不加,把GET_TIME注释掉即可

/* File:     timer.h
 *
 * Purpose:  Define a macro that returns the number of seconds that 
 *           have elapsed since some point in the past.  The timer
 *           should return times with microsecond accuracy.
 *
 * Note:     The argument passed to the GET_TIME macro should be
 *           a double, *not* a pointer to a double.
 *
 * Example:  
 *    #include "timer.h"
 *    . . .
 *    double start, finish, elapsed;
 *    . . .
 *    GET_TIME(start);
 *    . . .
 *    Code to be timed
 *    . . .
 *    GET_TIME(finish);
 *    elapsed = finish - start;
 *    printf("The code to be timed took %e seconds\n", elapsed);
 *
 * IPP:  Section 3.6.1 (pp. 121 and ff.) and Section 6.1.2 (pp. 273 and ff.)
 */
#ifndef _TIMER_H_
#define _TIMER_H_

#include <sys/time.h>

/* The argument now should be a double (not a pointer to a double) */
#define GET_TIME(now) { \
   struct timeval t; \
   gettimeofday(&t, NULL); \
   now = t.tv_sec + t.tv_usec/1000000.0; \
}

#endif

源程序代码

/*
 *编写一个Pthreads程序实现一个“任务队列”。主线程启动用户指定数量的线程,
 *这些线程进入条件等待状态。主线程生成一些任务(一定计算量),每生成一个新的任务,
 *就用条件变量唤醒一个线程,当这个唤醒线程执行完任务时,回到条件等待状态。
 *当主线程生成完所有任务,设置全局变量表示再没有要生成的任务了,并用一个广播唤醒所有线程。
 *为了清晰起见,建议任务采用链表操作。
 */

#include<stdlib.h>
#include<stdio.h>
#include<pthread.h>
#include "time.h"
#include<unistd.h>

typedef struct list_node_s{//链表节点
    int data;
    struct list_node_s* next;
}list_node_s;

typedef struct work_queue{//任务队列
    list_node_s* head;
    list_node_s* tail;
}work_queue;

/************全局区************/
int thread_count;//线程数
int work_count;//任务量
int finished = 0;//所有任务生成完成标记
pthread_cond_t cond_var;//条件变量:没有要生成的任务了,广播唤醒所有线程
pthread_mutex_t mutex;//互斥访问任务队列,粗粒度锁
work_queue q;//任务队列
int* data;//任务数据集合
/*******************************/

int Init(work_queue *queue_p)
{
    queue_p->head = (list_node_s*)malloc(sizeof(list_node_s));
    queue_p->tail = queue_p->head;
    queue_p->head->next = NULL;
    return 1;

}
//入队
int Push(work_queue*queue_p,int value)
{
    list_node_s* temp = (list_node_s*)malloc(sizeof(list_node_s));
    temp->data = value;
    temp->next = NULL;
    queue_p->tail->next = temp;
    queue_p->tail = temp;
    return 1;
}

//出队
int Pop(work_queue*queue_p)
{
    if(queue_p->head == queue_p->tail){//队列空
        return -1;
    }
    list_node_s *p = queue_p->head->next;
    if(p == NULL) return -1;
    int index = p->data;
    if(queue_p->tail == NULL) queue_p->tail = queue_p->head;
    queue_p->head->next = p->next;
    free(p);
    return index;//返回任务号
}

void Usage(char prog_name[]) {
   fprintf(stderr, "usage: %s ", prog_name); 
   fprintf(stderr, "<线程数> <主线程生成的任务量>\n");
   exit(0);
}  
//具体任务
long long Gen_work(int rank) 
{
    srand(0);
    for(int i=0;i<1000/(rank+1);i++)
        data[i] = rand();
    long long sum = 0;
    for(int i=0;i<1000/(rank+1);i++)
        sum+=data[i];
    return sum;
} 


void *Thread_work(void* rank)
{
    int my_rank = (int)rank;
    while(1){
        pthread_mutex_lock(&mutex);
        if(finished){
            if(q.head == q.tail || q.head->next == NULL){//所有任务已经被处理完了
                pthread_mutex_unlock(&mutex);
                break;
            }else{
                int index = Pop(&q);//返回任务ID
                pthread_mutex_unlock(&mutex);
                long long result = Gen_work(my_rank);//一定计算量的任务
                if(index!=-1)
                    printf("thread %d finished task %2d, result: %lld\n",my_rank,index,result);
            }
        }else{
            while(pthread_cond_wait(&cond_var,&mutex)!=0);
            //等待mutex解锁 让线程进入条件等待状态
            int index = Pop(&q);//返回任务ID
            pthread_mutex_unlock(&mutex);
            long long result = Gen_work(my_rank);//一定计算量的任务
            if(index!=-1)
                printf("thread %d finished task %d, result: %lld\n",my_rank,index,result);
        }
    }

}

int main(int argc,char* argv[])
{   
    if(argc != 3) Usage(argv[0]);
    thread_count = strtol(argv[1],NULL,10);
    work_count = strtol(argv[2],NULL,10);

    pthread_t* thread_handles;
    double start,finish;

    Init(&q);
    pthread_mutex_init(&mutex,NULL);
    thread_handles = malloc(thread_count*sizeof(pthread_t));
    data = malloc(100000*sizeof(int));
    GET_TIME(start);
    //启动用户指定数量的线程
    for(int i=0;i<thread_count; i++)
        pthread_create(&thread_handles[i], NULL,Thread_work, (void*)i);
    //主线程生成一些任务
    for(int i=0;i<work_count;i++){
        pthread_mutex_lock(&mutex);
        Push(&q,i);
        pthread_cond_signal(&cond_var);//唤醒一个线程
        pthread_mutex_unlock(&mutex);
    }
    finished = 1;
    printf("%d tasks are created\n",work_count);
    pthread_cond_broadcast(&cond_var);
    for (int i = 0; i < thread_count; i++)
        pthread_join(thread_handles[i], NULL);
    GET_TIME(finish);
    printf("run time:%.6f seoncds",finish-start);
    pthread_cond_destroy(&cond_var);
    pthread_mutex_destroy(&mutex);
    free(thread_handles);

    return 0;
}

内容概要:本文介绍了一种利用遗传算法优化BP神经网络进行回归预测的方法,并提供了完整的MATLAB程序代码。主要内容包括数据预处理、遗传算法与BP神经网络的结合、适应度函数的设计以及最终的预测结果展示。文中详细解释了如何将Excel格式的数据导入MATLAB并进行归一化处理,如何定义适应度函数来优化BP神经网络的参数(如激活函数和学习率),并通过遗传算法找到最优解。实验结果显示,在某工业数据集上,经过遗传算法优化后的BP神经网络预测精度显著提高,从原来的0.82提升到了0.91。此外,还提到了一些实用技巧,比如调整遗传代数、修改激活函数等方法进一步改进模型性能。 适合人群:对机器学习有一定了解的研究人员和技术爱好者,特别是那些希望深入了解遗传算法与BP神经网络结合应用的人士。 使用场景及目标:适用于需要快速构建高效回归预测模型的场景,尤其是当传统BP神经网络无法达到预期效果时。通过本篇文章的学习,读者能够掌握一种有效的优化手段,从而提高模型的泛化能力和预测准确性。 其他说明:代码可以直接应用于新的数据集,只需确保数据格式符合要求(Excel格式)。对于想要深入探索或改进现有模型的人来说,还可以尝试更换不同的激活函数或其他调节方式来获得更好的表现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值