我有一个程序,它将一个非常大的数组中的元素相加。我希望将此总和并行化。
#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)
答案 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)
使用分而治之算法
答案 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;
}