我最近编写了一个小数字运算程序,它基本上遍历一个N维网格,并在每个点执行一些计算.
for (int i1 = 0; i1 < N; i1++)
for (int i2 = 0; i2 < N; i2++)
for (int i3 = 0; i3 < N; i3++)
for (int i4 = 0; i4 < N; i4++)
histogram[bin_index(i1, i2, i3, i4)] += 1; // see bottom of question
Run Code Online (Sandbox Code Playgroud)
它运行良好,yadda yadda yadda,可爱的图形结果;-)然后我想,我的计算机上有2个核心,为什么不让这个程序多线程,所以我可以运行它两倍的速度?
现在,我的循环总共运行了大约十亿次计算,我需要一些方法将它们分散在线程中.我想我应该将计算分组为"任务" - 比如最外层循环的每次迭代都是一项任务 - 然后将任务分发给线程.我考虑过了
i1 % nthreads == n- 基本上预先确定哪些任务进入哪些线程i1下一个需要执行的任务的参数(在本例中) - 动态地将任务分配给线程有什么理由选择一种方法而不是另一种方法?还是我没想过的另一种方法?它甚至重要吗?
顺便说一下,我用C编写了这个特定的程序,但我想我也会在其他语言中再做同样的事情,所以答案不一定是C特定的.(如果有人知道用于Linux的C库可以做这种事情,我很想知道它)
编辑:在这种情况下bin_index是一个确定性函数,除了它自己的局部变量之外不会改变任何东西.像这样的东西:
int bin_index(int i1, int i2, …Run Code Online (Sandbox Code Playgroud) 过去一周我一直在写一个光线跟踪器,并且已经达到了足够多线程有意义的程度.我已经尝试使用OpenMP来并行化它,但是用更多线程运行它实际上比用一个线程运行它要慢.
阅读其他类似问题,特别是有关OpenMP的问题,一个建议是gcc更好地优化串行代码.但是,运行下面的编译代码的export OMP_NUM_THREADS=1速度是以下的两倍export OMP_NUM_THREADS=4.即两次运行的编译代码相同.
运行程序time:
> export OMP_NUM_THREADS=1; time ./raytracer
real 0m34.344s
user 0m34.310s
sys 0m0.008s
> export OMP_NUM_THREADS=4; time ./raytracer
real 0m53.189s
user 0m20.677s
sys 0m0.096s
Run Code Online (Sandbox Code Playgroud)
用户时间比实际小很多,这在使用多个核心时很不寻常 - 用户应该比实际大,因为多个核心同时运行.
我使用OpenMP并行化的代码
void Raytracer::render( Camera& cam ) {
// let the camera know to use this raytracer for probing the scene
cam.setSamplingFunc(getSamplingFunction());
int i, j;
#pragma omp parallel private(i, j)
{
// Construct a ray for each pixel.
#pragma omp for …Run Code Online (Sandbox Code Playgroud) 在配备Intel Pentium双核处理器T2370(Acer Extensa)的笔记本电脑上,我运行了一个简单的多线程加速测试.我正在使用Linux.代码粘贴在下面.虽然我期待加速2-3次,但我惊讶地发现速度减慢了2倍.我尝试了同样的gcc优化等级-O0 ... -O3,但每次我得到相同的结果.我正在使用pthreads.我也尝试了同样只有两个线程(而不是代码中的3个线程),但性能类似.
可能是什么原因?更快的版本需要相当长的时间 - 大约20秒 - 所以它似乎不是启动开销的问题.
注意:这个代码有很多错误(事实上它没有多大意义,因为串行和并行版本的输出会有所不同).目的只是"获得"相同数量指令的加速比较.
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
class Thread{
private:
pthread_t thread;
static void *thread_func(void *d){((Thread *)d)->run();}
public:
Thread(){}
virtual ~Thread(){}
virtual void run(){}
int start(){return pthread_create(&thread, NULL, Thread::thread_func, (void*)this);}
int wait(){return pthread_join(thread, NULL);}
};
#include <iostream>
const int ARR_SIZE = 100000000;
const int N = 20;
int arr[ARR_SIZE];
int main(void)
{
class Thread_a:public Thread{
public:
Thread_a(int* a): arr_(a) {}
void run()
{
for(int n = …Run Code Online (Sandbox Code Playgroud)