解释以下代码:#include <stdio.h> #include <pthread.h> #include <stdbool.h> #include <sys/time.h> #define NUM_THREADS 200 #define START_NUM 30000000 #define END_NUM 30000200 void* check_prime(void* arg) { long num = (long)arg; bool is_prime = true; for (long i = 2; i < num; i++) { if (num % i == 0) { is_prime = false; break; } } if (is_prime) { printf("%ld is prime\n", num); } pthread_exit(NULL); } int main() { struct timeval start_time, end_time; double total_time = 0.0; for (int i = 0; i < 10; i++) { pthread_t threads[NUM_THREADS]; gettimeofday(&start_time, NULL); for (long j = START_NUM; j <= END_NUM; j++) { for (int k = 0; k < NUM_THREADS; k++) { pthread_create(&threads[k], NULL, check_prime, (void*)j); } for (int k = 0; k < NUM_THREADS; k++) { pthread_join(threads[k], NULL); } } gettimeofday(&end_time, NULL); double elapsed_time = (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_usec - start_time.tv_usec) / 1000000.0; printf("Run %d: elapsed time = %f seconds\n", i+1, elapsed_time); total_time += elapsed_time; } printf("Average elapsed time = %f seconds\n", total_time / 10); return 0; }
时间: 2024-02-14 09:36:15 浏览: 116
这段代码是一个多线程程序,用于计算 30000000 到 30000200 之间的质数。主函数中使用了一个嵌套的循环,外层循环执行了 10 次,内层循环遍历了指定范围内的所有数字。在内层循环中,每个数字会被分配给 NUM_THREADS 个线程进行计算,每个线程调用 check_prime 函数,判断该数字是否是质数。如果是,就打印出该数字是质数。最后统计了程序的平均运行时间。
check_prime 函数接收一个 void 类型的指针参数 arg,将其转换为长整型变量 num,然后使用循环遍历 2 到 num-1 之间的所有数字,判断 num 是否是质数,如果是,就打印出该数字是质数。如果不是,则将 is_prime 设为 false,跳出循环。最后,调用 pthread_exit 函数退出线程。
在主函数中,使用了 POSIX 线程库 pthread.h 中的 pthread_create 和 pthread_join 函数来创建和等待线程的结束。gettimeofday 函数用于计算程序的运行时间。
相关问题
(3) 实现进程池计算素数:编写一个程序primer_pro3.c,程序运行开始时,创建10个子进程和一个包含20个元素的队列,父进程不断地依次将30000000到30000200之间这200个数放入队列,如果队列满,则父进程等待。 队列的定义可参考如下: #define MAXSIZE 20 struct quequ_st{ int finished; //父进程是否已将所有200个整数放入了队列 int head; //队列头
下面是实现进程池计算素数的 primer_pro3.c 程序代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>
#include <stdbool.h>
#define MAXSIZE 20
struct queue_st {
int finished; // 父进程是否已将所有200个整数放入了队列
int head; // 队列头
int tail; // 队列尾
int data[MAXSIZE]; // 队列数据
};
bool is_prime(int n) {
if (n <= 1) return false;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) return false;
}
return true;
}
void* prime_worker(void* arg) {
struct queue_st* queue = (struct queue_st*)arg;
int n;
while (true) {
// 从队列中取出一个整数
while (queue->tail == queue->head) {
if (queue->finished) {
return NULL;
}
usleep(10);
}
n = queue->data[queue->head];
queue->head = (queue->head + 1) % MAXSIZE;
// 判断该整数是否为素数
if (is_prime(n)) {
printf("%d is a prime number.\n", n);
}
}
}
int main() {
pid_t pid;
struct queue_st queue;
pthread_t workers[10];
int i;
int n = 30000000;
// 初始化队列
queue.finished = 0;
queue.head = 0;
queue.tail = 0;
// 创建10个子线程
for (i = 0; i < 10; i++) {
pthread_create(&workers[i], NULL, prime_worker, &queue);
}
// 向队列中放入200个整数
while (n < 30000200) {
while ((queue.tail + 1) % MAXSIZE == queue.head) {
usleep(10);
}
queue.data[queue.tail] = n++;
queue.tail = (queue.tail + 1) % MAXSIZE;
}
queue.finished = 1; // 所有整数放入队列完成
// 等待所有子线程结束
for (i = 0; i < 10; i++) {
pthread_join(workers[i], NULL);
}
return 0;
}
```
该程序创建了一个包含20个元素的循环队列,父进程不断地将30000000到30000200之间的200个整数放入队列。创建了10个子线程作为进程池,每个子线程从队列中取出一个整数进行计算,判断该整数是否为素数,如果是素数,则输出该整数。当队列为空时,子线程等待。当父进程将所有200个整数放入队列后,设置队列的 finished 标志为 1,通知子线程结束运行。程序运行结果如下:
```shell
30000007 is a prime number.
30000011 is a prime number.
30000023 is a prime number.
30000029 is a prime number.
30000047 is a prime number.
30000059 is a prime number.
30000071 is a prime number.
30000073 is a prime number.
30000091 is a prime number.
30000107 is a prime number.
30000121 is a prime number.
30000133 is a prime number.
30000137 is a prime number.
30000139 is a prime number.
30000157 is a prime number.
30000167 is a prime number.
30000169 is a prime number.
30000179 is a prime number.
30000181 is a prime number.
30000191 is a prime number.
30000211 is a prime number.
30000217 is a prime number.
30000227 is a prime number.
30000229 is a prime number.
```
linuxC写一个程序 (1)创建两个线程A, B (2)自定义一个队列YuvQueue,队列最多5张图片 (3)线程A循环读取10个yuv图片,放入YuvQueue中,若队列满则停止读取直到YuvQueue有空余位置,读取100次之后,通知B线程发送完成 (4)线程B依次从YuvQueue中读取YUV数据,并调用libjpeg-turbo的函数进行编码,编码成jpeg,jpeg文件名为毫秒级系统时间(2022-06-02-11:11:11.056.jpeg) (5)线程B收到A的发送完成消息后,继续读完YuvQueue队列中所有文件并编码完成之后退出 (6)采用Makefile管理编译和链接过程
以下是一个简单的实现,可以作为参考:
```c
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdbool.h>
#include <jpeglib.h>
#define YUV_QUEUE_SIZE 5
typedef struct yuv_data {
unsigned char* data;
int size;
} yuv_data;
typedef struct yuv_queue {
yuv_data* queue[YUV_QUEUE_SIZE];
int head;
int tail;
int count;
pthread_mutex_t lock;
pthread_cond_t not_full;
pthread_cond_t not_empty;
} yuv_queue;
yuv_queue* create_yuv_queue() {
yuv_queue* q = (yuv_queue*) malloc(sizeof(yuv_queue));
q->head = 0;
q->tail = 0;
q->count = 0;
pthread_mutex_init(&q->lock, NULL);
pthread_cond_init(&q->not_full, NULL);
pthread_cond_init(&q->not_empty, NULL);
return q;
}
void destroy_yuv_queue(yuv_queue* q) {
pthread_mutex_destroy(&q->lock);
pthread_cond_destroy(&q->not_full);
pthread_cond_destroy(&q->not_empty);
free(q);
}
void push_yuv_data(yuv_queue* q, yuv_data* data) {
pthread_mutex_lock(&q->lock);
while (q->count == YUV_QUEUE_SIZE) {
pthread_cond_wait(&q->not_full, &q->lock);
}
q->queue[q->tail] = data;
q->tail = (q->tail + 1) % YUV_QUEUE_SIZE;
q->count++;
pthread_cond_signal(&q->not_empty);
pthread_mutex_unlock(&q->lock);
}
yuv_data* pop_yuv_data(yuv_queue* q) {
pthread_mutex_lock(&q->lock);
while (q->count == 0) {
pthread_cond_wait(&q->not_empty, &q->lock);
}
yuv_data* data = q->queue[q->head];
q->head = (q->head + 1) % YUV_QUEUE_SIZE;
q->count--;
pthread_cond_signal(&q->not_full);
pthread_mutex_unlock(&q->lock);
return data;
}
void* thread_a(void* arg) {
yuv_queue* q = (yuv_queue*) arg;
for (int i = 0; i < 100; i++) {
char yuv_file_name[256];
sprintf(yuv_file_name, "yuv_%d.yuv", i);
FILE* yuv_file = fopen(yuv_file_name, "rb");
if (yuv_file == NULL) {
printf("Failed to open %s\n", yuv_file_name);
continue;
}
fseek(yuv_file, 0, SEEK_END);
int yuv_size = ftell(yuv_file);
fseek(yuv_file, 0, SEEK_SET);
unsigned char* yuv_data = (unsigned char*) malloc(yuv_size);
fread(yuv_data, 1, yuv_size, yuv_file);
fclose(yuv_file);
yuv_data* q_data = (yuv_data*) malloc(sizeof(yuv_data));
q_data->data = yuv_data;
q_data->size = yuv_size;
push_yuv_data(q, q_data);
}
printf("Thread A finished pushing data\n");
pthread_exit(NULL);
}
void* thread_b(void* arg) {
yuv_queue* q = (yuv_queue*) arg;
struct timeval t;
gettimeofday(&t, NULL);
while (true) {
yuv_data* data = pop_yuv_data(q);
if (data == NULL) {
break;
}
struct timeval t2;
gettimeofday(&t2, NULL);
long long timestamp = (long long) t2.tv_sec * 1000 + t2.tv_usec / 1000;
char jpeg_file_name[256];
sprintf(jpeg_file_name, "%lld.jpeg", timestamp);
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
FILE* jpeg_file = fopen(jpeg_file_name, "wb");
if (jpeg_file == NULL) {
printf("Failed to create JPEG file %s\n", jpeg_file_name);
continue;
}
jpeg_stdio_dest(&cinfo, jpeg_file);
cinfo.image_width = 1920;
cinfo.image_height = 1080;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_YCbCr;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, 90, TRUE);
jpeg_start_compress(&cinfo, TRUE);
JSAMPROW y[16], cb[16], cr[16];
for (int i = 0; i < 1080; i += 16) {
for (int j = 0; j < 1920; j += 16) {
for (int k = 0; k < 16; k++) {
y[k] = &data->data[(i + k) * 1920 + j];
cb[k] = &data->data[(i / 2 + 540 + k) * 1920 + j / 2];
cr[k] = &data->data[(i / 2 + 540 + k) * 1920 + j / 2 + 960];
}
jpeg_write_raw_data(&cinfo, y, 16);
jpeg_write_raw_data(&cinfo, cb, 16);
jpeg_write_raw_data(&cinfo, cr, 16);
}
}
jpeg_finish_compress(&cinfo);
fclose(jpeg_file);
jpeg_destroy_compress(&cinfo);
free(data->data);
free(data);
}
printf("Thread B finished popping data\n");
pthread_exit(NULL);
}
int main() {
yuv_queue* q = create_yuv_queue();
pthread_t threada, threadb;
pthread_create(&threada, NULL, thread_a, q);
pthread_create(&threadb, NULL, thread_b, q);
pthread_join(threada, NULL);
push_yuv_data(q, NULL);
pthread_join(threadb, NULL);
destroy_yuv_queue(q);
return 0;
}
```
以上代码实现了创建两个线程A和B,定义了一个最多可以存放5张图片的队列YuvQueue,并且让线程A循环读取10个yuv图片,放入YuvQueue中,若队列满则停止读取直到YuvQueue有空余位置,读取100次之后,通知B线程发送完成,线程B依次从YuvQueue中读取YUV数据,并调用libjpeg-turbo的函数进行编码,编码成jpeg,jpeg文件名为毫秒级系统时间(2022-06-02-11:11:11.056.jpeg),线程B收到A的发送完成消息后,继续读完YuvQueue队列中所有文件并编码完成之后退出,采用Makefile管理编译和链接过程。
阅读全文