gpt4 book ai didi

c - 为什么我的并行代码比串行代码慢?

转载 作者:行者123 更新时间:2023-11-30 18:39:09 25 4
gpt4 key购买 nike

问题

大家好,我有一个程序(来自网络),我打算通过使用pthreads将其转换为并行版本来加速。但令人惊讶的是,它的运行速度比串行版本。程序如下:

# include <stdio.h>

//fast square root algorithm
double asmSqrt(double x)
{
__asm__ ("fsqrt" : "+t" (x));
return x;
}

//test if a number is prime
bool isPrime(int n)
{
if (n <= 1) return false;
if (n == 2) return true;
if (n%2 == 0) return false;

int sqrtn,i;
sqrtn = asmSqrt(n);

for (i = 3; i <= sqrtn; i+=2) if (n%i == 0) return false;
return true;
}

//number generator iterated from 0 to n
int main()
{
n = 1000000; //maximum number
int k,j;

for (j = 0; j<= n; j++)
{
if(isPrime(j) == 1) k++;
if(j == n) printf("Count: %d\n",k);
}
return 0;
}

首次尝试并行化

我让pthread管理for循环

# include <stdio.h>
.
.

int main()
{
.
.
//----->pthread code here<----
for (j = 0; j<= n; j++)
{
if(isPrime(j) == 1) k++;
if(j == n) printf("Count: %d\n",k);
}
return 0;
}

嗯,它的运行速度比串行慢

第二次尝试

我将 for 循环 分为两个线程,并使用 pthreads 并行运行它们

但是,它的运行速度仍然较慢,我打算它的运行速度可能会快两倍或更快。但事实并非如此!

顺便说一句,这是我的并行代码:

# include <stdio.h>
# include <pthread.h>
# include <cmath>

# define NTHREADS 2

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int k = 0;

double asmSqrt(double x)
{
__asm__ ("fsqrt" : "+t" (x));
return x;
}

struct arg_struct
{
int initialPrime;
int nextPrime;
};

bool isPrime(int n)
{
if (n <= 1) return false;

if (n == 2) return true;

if (n%2 == 0) return false;

int sqrtn,i;
sqrtn = asmSqrt(n);

for (i = 3; i <= sqrtn; i+=2) if (n%i == 0) return false;

return true;
}

void *parallel_launcher(void *arguments)
{
struct arg_struct *args = (struct arg_struct *)arguments;

int j = args -> initialPrime;
int n = args -> nextPrime - 1;

for (j = 0; j<= n; j++)
{
if(isPrime(j) == 1)
{
printf("This is prime: %d\n",j);
pthread_mutex_lock( &mutex1 );
k++;
pthread_mutex_unlock( &mutex1 );
}

if(j == n) printf("Count: %d\n",k);
}
pthread_exit(NULL);
}

int main()
{
int f = 100000000;
int m;

pthread_t thread_id[NTHREADS];
struct arg_struct args;

int rem = (f+1)%NTHREADS;
int n = floor((f+1)/NTHREADS);

for(int h = 0; h < NTHREADS; h++)
{
if(rem > 0)
{
m = n + 1;
rem-= 1;
}
else if(rem == 0)
{
m = n;
}

args.initialPrime = args.nextPrime;
args.nextPrime = args.initialPrime + m;

pthread_create(&thread_id[h], NULL, &parallel_launcher, (void *)&args);
pthread_join(thread_id[h], NULL);
}
// printf("Count: %d\n",k);
return 0;
}

注意:操作系统:Fedora 21 x86_64,编译器:gcc-4.4,处理器:Intel Core i5(2 个物理核心,4 个逻辑核心),内存:6 GB,硬盘:340 GB,

最佳答案

您需要将要检查的素数范围分成 n 部分,其中 n 是线程数。

每个线程运行的代码变为:

typedef struct start_end {
int start;
int end;
} start_end_t;

int find_primes_in_range(void *in) {
start_end_t *start_end = (start_end_t *) in;

int num_primes = 0;
for (int j = start_end->start; j <= start_end->end; j++) {
if (isPrime(j) == 1)
num_primes++;
}
pthread_exit((void *) num_primes;
}

main 例程首先启动所有调用 find_primes_in_range 的线程,然后为每个线程调用 pthread_join。它将 find_primes_in_range 返回的所有值相加。这可以避免锁定和解锁共享计数变量。

这将使工作并行化,但每个线程的工作量将不相等。这个问题可以解决,但比较复杂。

关于c - 为什么我的并行代码比串行代码慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30838047/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com