CPU_多线程操作图片_代码详解
·
Pthreads库
pthread_attr() 初始化线程的各项属性
pthread_attr_setdetachstate() 为初始化的线程设置属性
pthread_create() 创建一个线程
| 第一个参数 | 是每个线程的“句柄”,对操作系统非常重要,使操作系统能够跟踪线程。 |
| 第二个参数 | 对于所有线程都相同,内容是线程属性 |
| 第三个参数 | 告诉线程要执行的任务 |
| 第四个参数 | 经过一些指针操作后,该参数指向TheParam[i],每个线程知道自己是谁 |
pthread_attr_destroy()
pthread_join()合并线程
用于将任何给定的线程合并到最初创建它的线程中。你可以将“合并”过程想象成“毁灭”线程,或者父线程“吞食”刚刚创建的线程。
示例
main主函数被重复执行3次,每次执行使用2个线程完成计算任务。
#include <pthread.h>
#include <stdint.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h> // sleep()函数头文件
#define REPS 3
#define MAXTHREADS 128
long NumThreads=2; // Total number of threads working in parallel 并行的线程总数
int ThParam[MAXTHREADS]; // Thread parameters ...线程参数
pthread_t ThHandle[MAXTHREADS]; // Thread handles 线程句柄
pthread_attr_t ThAttr; // Pthread attrributes
void *MTFlip(void* tid)
{
int i;
long ts = *((int *) tid); // My thread ID is stored here
printf("\ntid=%d\n",tid);
for(i=0;i<3;i++){
sleep(1);
printf("\n 正在使用ts=%d 执行计算任务,循环到i=%d\n",tid,i);
}
pthread_exit(0);
}
int main(int argc, char** argv)
{
int a,i,ThErr;
struct timeval t;
double StartTime, EndTime;
double TimeElapsed;
if((NumThreads<1) || (NumThreads>MAXTHREADS)){
printf("\nNumber of threads must be between 1 and %u... Exiting abruptly\n",MAXTHREADS);
exit(EXIT_FAILURE);
}
else{
if(NumThreads != 1){
printf("\nExecuting the multi-threaded version with %li threads ...\n",NumThreads);
}
else{
printf("\nExecuting the serial version ...\n");
}
}
gettimeofday(&t, NULL);
StartTime = (double)t.tv_sec*1000000.0 + ((double)t.tv_usec);
if(NumThreads >1){
for(a=0; a<REPS; a++){
pthread_attr_init(&ThAttr);
pthread_attr_setdetachstate(&ThAttr, PTHREAD_CREATE_JOINABLE);
printf("\n 代码重复执行第 %d 次\n",a+1);
for(i=0; i<NumThreads; i++){
ThParam[i] = i;
ThErr = pthread_create(&ThHandle[i], &ThAttr, MTFlip, (void *)&ThParam[i]);
if(ThErr != 0){
printf("\nThread Creation Error %d. Exiting abruptly... \n",ThErr);
exit(EXIT_FAILURE);
}
}
pthread_attr_destroy(&ThAttr);
for(i=0; i<NumThreads; i++){
pthread_join(ThHandle[i], NULL);
}
}
}else{
printf("\n单线程串行执行代码\n");
}
gettimeofday(&t, NULL);
EndTime = (double)t.tv_sec*1000000.0 + ((double)t.tv_usec);
TimeElapsed=(EndTime-StartTime)/1000.00;
TimeElapsed/=(double)REPS;
printf("\n\nTotal execution time: %9.4f ms ",TimeElapsed);
return (EXIT_SUCCESS);
}
多线程对数据进行分块处理
利用多线程数量,将数据处理进行分块遍历,并建立相应的处理索引序号。
void *MTFlipV(void* tid)
{
struct Pixel pix; //temp swap pixel
int row, col;
printf("函数入参是void*泛型指针(通用指针),它是指针,命名为tid,指的是一个地址,十进制表示为为%d,十六进制表示为%x,地址号为%p\n",tid,tid,tid);
printf("void*泛型指针的sizeof为%zu\n",sizeof(tid));
printf("void*泛型指针不能直接解引用,需要被强制类型转换\n");
long ts = *((int *) tid); // My thread ID is stored here
printf("%\n tid=%d, ts=%d\n",tid,ts);
printf("ip.Hbytes=%d\n", ip.Hbytes);
ts *= ip.Hbytes/NumThreads; // start index 数据分块遍历的开始索引
// ts =ts * (ip.Hbytes/Numthread)
printf("\nstart index = %d\n",ts);
long te = ts+ip.Hbytes/NumThreads-1; // end index 数据分块遍历的结束索引
printf("\nend index = %d\n",te);
for(col=ts; col<=te; col+=3)
{
....
}
}

long ts = *((int *) tid)

指针解引用
指针代表的是地址,访问地址背后代表的数据,就是指针的解引用。* 表示的是运算符
#include<stdio.h>
int main(){
int a=4;
int b=8;
int *p1=&a;
int *p2=&b;
printf("变量a的内存地址为%p\n",&a);
printf("指针p1的内存地址为%p\n",p1);
printf("指针变量的解引用后数值为%d\n",*p1);
printf("\n变量a的内存地址为%p\n",&b);
printf("指针p1的内存地址为%p\n",p2);
printf("指针变量的解引用后数值为%d\n",*p2);
long c=0;
void *p3=&c;
long d = *((int*)p3);
printf("\np3指针解引用的值为%d\n",*(int*)p3);
}

复合赋值运算符 *=
ts *= ip.Hbytes/NumThreads; 表示 t s = t s ∗ ( i p . H b y t e s / N u m t h r e a d ) ts =ts * (ip.Hbytes/Numthread) ts=ts∗(ip.Hbytes/Numthread)
toupper() 小写字母转换为大写字母
C 库函数 int toupper(int c)把小写字母转换为大写字母。
反参:
如果 c 有相对应的大写字母,则该函数返回 c 的大写字母,否则 c 保持不变。返回值是一个可被隐式转换为 char 类型的 int 值。
#include <stdio.h>
#include <ctype.h>
int main()
{
int i = 0;
char str[] = "runoob";
while(str[i])
{
putchar (toupper(str[i]));
i++;
}
return(0);
}

gettimeofday() 获取到当前时间的秒数
该函数的头文件在/usr/include/sys/time.h头文件中。
函数原型:int gettimeofday(struct timeval*tv, struct timezone *tz);
用到两个结构体: timeval 和 timezone
这两个结构体定义在/usr/include/linux/time.h头文件中。
示例2
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
int main(){
struct timeval tv;
struct timezone tz;
gettimeofday (&tv, &tz);
printf("\ntv_sec; %d\n", tv.tv_sec);
printf("tv_usec; %d\n", tv.tv_usec);
printf("tz_minuteswest; %d\n", tz.tz_minuteswest);
printf("tz_dsttime, %d\n", tz.tz_dsttime);
}

示例2
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h> // sleep()函数头文件
#define REPS 1
int main()
{
struct timeval t;
double StartTime, EndTime;
double TimeElapsed;
gettimeofday(&t, NULL);
StartTime = (double)t.tv_sec*1000000.0 + ((double)t.tv_usec);
sleep(30); //休眠30秒
gettimeofday(&t, NULL);
EndTime = (double)t.tv_sec*1000000.0 + ((double)t.tv_usec);
TimeElapsed=(EndTime-StartTime)/1000.00;
TimeElapsed/=(double)REPS;
printf("\n\nTotal execution time: %9.4f ms ",TimeElapsed);
}

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)