使用GCC编译一个C程序,在Linux上利用所有CPU核心

3

我有一个用于加法的C语言示例程序。当我使用GCC编译并运行它时,它只使用了一个CPU核心。

是否有一种方法可以编译C程序,以便在Linux中可以使用所有CPU核心。

我以前是这样编译的:gcc -O3 malloc.c

代码:

#include <stdio.h>
#include <time.h>
#include <malloc.h>

int main() {
        float *ptr;
        unsigned long long i;

        ptr = (float*) malloc(8000000000 * sizeof(float));

        for(i=0; i<8000000000; i++) {
                ptr[i] = i/10000;
        }

        clock_t tic = clock();

        for(i=0; i<8000000000; i++) {
                ptr[i] = (i/10000)+1.0;
        }

        clock_t toc = clock();

        printf("Elapsed: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC);

        return 0;
}

1
<malloc.h> is non standard and perhaps deprecated. Use <stdlib.h> - Basile Starynkevitch
@LethalProgrammer:make -j 在编译时很重要,而不是在运行时。 - Basile Starynkevitch
@BasileStarynkevitch,我不确定OP要求什么,所以我只是提出了澄清问题的问题。如果他想在运行时执行此操作,那么我同意您没有使用make的观点。 - danglingpointer
2
如果它就像翻开一个开关一样简单,为什么不默认打开呢? - el.pescado - нет войне
顺便提一下,-O 开关只是用于指定您想要的优化级别。 - babon
显示剩余6条评论
4个回答

16

有没有办法编译一个C程序,使其在Linux中可以使用所有CPU核心。

不可能像你想象的那样神奇地实现程序的并行化。程序的并行化是一个非常困难的主题,通常不能自动完成。顺便说一下,并行程序可能不像您希望的那样高效(要注意阿姆达尔定律)。

但是,您可以进行设计编码并行程序。例如,您可以使用POSIX线程。请注意,这很棘手!首先阅读一些Pthread教程。您无法确定所有核心是否会被使用(因为它们由内核管理),但在实践中,这很可能发生。还要了解处理器亲和性

你还可以使用OpenMPOpenACC。你可以使用OpenCL编写一些数值内核。你可以采用多进程方法(例如分叉几个进程,使用进程间通信),也许使用MPI。还要看看MapReduce方法,0mq库(以及其他许多库)。
你可以阅读有关操作系统的文章,例如操作系统:三个简单部分。你也可以阅读有关Linux系统编程的文章,例如高级Linux编程(或一些更新的书籍)。另请参见intro(2)syscalls(2) & pthreads(7)
请注意,设计、编码和调试parallel(或并发或distributed)应用程序非常困难。考虑到开发时间的成本(以及获取相关技能可能需要数年的时间),没有No Silver Bullet

将现有的现实顺序应用程序转换为并行应用程序并不是非常现实的;通常您需要从头设计一个并行程序。


-ftree-parallelize-loops=4 在 gcc 中还有效吗?如果是的话,在这种简单情况下,对于循环中具有编译时常量大迭代次数的情况,它可能会起作用。 - Peter Cordes
可能是的,但你应该尝试一下(答案可能与编译器版本有关)。 - Basile Starynkevitch

3

尝试在您的for循环正上方添加以下编译器指示:

#pragma omp parallel for
for(i=0; i<8000000000; i++) {
    ptr[i] = i/10000;
}

当您调用gcc时,请将-fopenmp选项添加到构建选项中。默认情况下,OpenMP将创建与计算机中的核心数量相同的线程,并在它们之间平均分配工作负载。

您可以查看此文章以获取有关OpenMP的更多信息。


很好!这将第二个for循环的时间从8.48秒改为了1.48秒。这是快了5.7倍,这在我的i7 CPU上有6个核心是可以预期的。 - Thomas Padron-McCarthy

1
你需要创建多个线程。否则只有一个线程,而且它在单个核心上运行(一次只能运行一个)。
查看有关线程的教程,特别是 pthreads,以了解如何使用线程。或者您可以使用 fork 系统调用将程序分成多个进程,每个进程一个线程。

1
我认为线程或进程之间的同步和通信并不容易。我的观点是它很困难 - Basile Starynkevitch
@BasileStarynkevitch:我认为每个人都同意你的观点。我认为triplee的意思是调用pthread_create很容易,但其余的部分很难。 - Thomas Padron-McCarthy
但是,即使对于问题中给出的简单代码,pthread_create 也不足够! - Basile Starynkevitch
据我所知,创建多个线程/进程并不能保证它们会使用多个核心。我错了吗? - babon
@BasileStarynkevitch 谢谢。但是,我认为这正是OP想要实现的,以我个人的看法... - babon
显示剩余4条评论

0

您可以在程序中创建n(n为核心数)个线程,然后可以设置每个线程的CPU亲和力,使其绑定到特定的CPU Coresched_setaffinitypthread_setaffinity_np是允许您设置CPU亲和力的函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接