大型数组中元素的并行和

时间:2013-04-29 06:21:59

标签: java c++ c multithreading pthreads

我有一个程序,它将一个非常大的数组中的元素相加。我希望将此总和并行化。

#define N = some_very_large_no; // say 1e12
float x[N]; // read from a file
float sum=0.0;
main()
{

for (i=0, i<N, i++)

sum=sum+x[i];

}

如何使用线程并行化这个总和(c / c ++ / Java,任何代码示例都可以)?如果机器中有8个核心以获得最佳性能,我应该使用多少个线程?

编辑:N可能非常大(实际大于1e6),并且根据我从中读取数据的文件大小而有所不同。该文件的顺序为GB。

编辑:N更改为较大的值(1e12到1e16)

7 个答案:

答案 0 :(得分:3)

在Java中你可以写

int cpus = Runtime.getRuntime().availableProcessors();
// would keep this of other tasks as well.
ExecutorService service = Executors.newFixedThreadPool(cpus);

float[] floats = new float[N];

List<Future<Double>> tasks = new ArrayList<>();
int blockSize = (floats.length + cpus - 1) / cpus;
for (int i=0, i < floats.length, i++) {
    final start = blockSize * i;
    final end = Math.min(blockSize * (i+1), floats.length);
    tasks.add(service.submit(new Callable<Double>() {
        public Double call() {
            double d= 0;
            for(int j=start;j<end;j++)
                d += floats[j];
            return d;
        }
     });
}
double sum = 0;
for(Future<Double> task: tasks)
    sum += task.get();

正如WhozCraig所提到的,可能有一百万个浮点数不足以需要多个线程,或者你可能会发现你的瓶颈是你从主内存加载数组的速度(单线程资源)如果您包含获取数据的成本,则无法假设它会更快。

答案 1 :(得分:3)

你说数组来自一个文件。如果你对程序的不同部分计时,你会发现,与从磁盘读取数据所需的时间相比,对元素求和所花费的时间可以忽略不计。从Amdahl's Law开始,通过并行化总结没有任何好处。

如果您需要提高性能,则应专注于提高I / O吞吐量。

答案 2 :(得分:2)

您可以使用多个线程(超过核心)。但没有线程&amp;它的性能取决于你的算法如何工作。  由于数组长度为100000,因此创建x线程&amp;每个都会计算arr [x]到arr [x + limit]。你必须设置限制,以便不与其他线程和没有元素应该保持未使用状态。 线程创建:

   pthread_t tid[COUNT];
    int i = 0;
        int err;
        while (i < COUNT) 
        {
            void *arg;
            arg = x; //pass here a no which will tell from where this thread will use arr[x]
            err = pthread_create(&(tid[i]), NULL, &doSomeThing, arg);
            if (err != 0)
                printf("\ncan't create thread :[%s]", strerror(err));
            else
            {
                //printf("\n Thread created successfully\n");
            }

            i++;
        }
       // NOW CALCULATE....
        for (int i = 0; i < COUNT; i++) 
        {
            pthread_join(tid[i], NULL);
        }
}

void* doSomeThing(void *arg) 
{
    int *x;
    x = (int *) (arg);
   // now use this x to start the array sum from arr[x] to ur limit which should not overlap to other thread
}

答案 3 :(得分:0)

使用分而治之算法

  • 将数组划分为2个或更多(继续递归分割,直到获得具有可管理大小的数组)
  • 开始计算子阵列(分割数组)的总和(使用单独的线程
  • 最后将所有子阵列生成的总和(从所有线程中)添加到一起以生成最终结果

答案 4 :(得分:0)

正如其他人所说,阅读文件的时间成本几乎肯定会比计算总和的时间要大得多。它是文本文件还是二进制文件?如果数字存储为文本,那么根据您的实现,读取它们的成本可能非常高。

您还应该小心添加大量浮动。由于它们的精度有限,阵列后期的小值可能无助于求和。至少考虑使用double来积累值。

答案 5 :(得分:0)

你可以在c中使用pthreads来解决你的问题 这是我的 N=4 代码(您可以更改它以满足您的需要) 要运行此代码,请应用以下命令: gcc -pthread test.c -o 测试 ./测试

<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@color/black"
    >


    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="@id/logoGuideline"
        app:layout_constraintBottom_toBottomOf="@id/logoGuideline"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:srcCompat="@drawable/myImage"/>

    <TextView
        android:id="@+id/info1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        app:layout_constraintTop_toBottomOf="@id/infoGuideline"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:textColor="@color/white"
        android:text="Hello World" />


    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/logoGuideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.2"
        />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/infoGuideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.4"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

答案 6 :(得分:0)

OpenMP 支持内置归约。编译时添加标志 -fopenmp。

#include <omp.h>
#define N = some_very_large_no; // say 1e12
float x[N]; // read from a file
int main()
{

float sum = 0.0;
#pragma omp parallel for reduction(+:sum)
for (i=0, i<N, i++)
  sum=sum+x[i];

return 0;
}