在 C 中用多个线程填充数组
Fill array with multiple threads in C
我有以下用多个线程填充数组的代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define MAX_ITEMS 67108864
#define LINES_PER_THREAD 8388608
#define THREADS 8
static int *array;
static pthread_t pids[THREADS];
static int args[THREADS];
static void init_array_line(int *line) {
int i, max;
i = *line;
max = i + LINES_PER_THREAD;
for (i; i < max; i++)
array[i] = rand() % 10000 + 1;
}
static void init_array() {
int i;
for ( i = 0; i < THREADS; i++) {
args[i]=i* LINES_PER_THREAD;
pthread_create(pids + i, NULL, &init_array_line, args + i);;
}
}
static wait_all() {
for (int i = 0; i < THREADS; i++) {
pthread_join(pids[i], NULL);
}
}
int
main(int argc, char **argv)
{
array = (int *)malloc(MAX_ITEMS * sizeof(int));
init_array();
wait_all();
}
我给每个线程 1/8 的数组来填充 LINES_PER_THREAD
,但似乎比正常填充它需要更长的时间。任何建议为什么会这样?
我怀疑主要瓶颈是对 rand()
的调用。 rand()
不需要线程安全。因此,当多个线程可以同时调用 rand()
时,它不能安全地用于多线程程序。但是 Glibc 实现使用内部锁来防止此类使用。这有效地序列化了所有线程中对 rand()
的调用,从而严重影响了程序的多线程特性。而是使用 rand_r()
,它不需要维护任何内部状态(因为调用者需要维护)并且至少可以解决您问题的这方面。
一般来说,如果线程没有做足够的工作,那么线程 creation/synchronization 开销可能会超过使用线程的多核系统上可用的并发性。
我有以下用多个线程填充数组的代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define MAX_ITEMS 67108864
#define LINES_PER_THREAD 8388608
#define THREADS 8
static int *array;
static pthread_t pids[THREADS];
static int args[THREADS];
static void init_array_line(int *line) {
int i, max;
i = *line;
max = i + LINES_PER_THREAD;
for (i; i < max; i++)
array[i] = rand() % 10000 + 1;
}
static void init_array() {
int i;
for ( i = 0; i < THREADS; i++) {
args[i]=i* LINES_PER_THREAD;
pthread_create(pids + i, NULL, &init_array_line, args + i);;
}
}
static wait_all() {
for (int i = 0; i < THREADS; i++) {
pthread_join(pids[i], NULL);
}
}
int
main(int argc, char **argv)
{
array = (int *)malloc(MAX_ITEMS * sizeof(int));
init_array();
wait_all();
}
我给每个线程 1/8 的数组来填充 LINES_PER_THREAD
,但似乎比正常填充它需要更长的时间。任何建议为什么会这样?
我怀疑主要瓶颈是对 rand()
的调用。 rand()
不需要线程安全。因此,当多个线程可以同时调用 rand()
时,它不能安全地用于多线程程序。但是 Glibc 实现使用内部锁来防止此类使用。这有效地序列化了所有线程中对 rand()
的调用,从而严重影响了程序的多线程特性。而是使用 rand_r()
,它不需要维护任何内部状态(因为调用者需要维护)并且至少可以解决您问题的这方面。
一般来说,如果线程没有做足够的工作,那么线程 creation/synchronization 开销可能会超过使用线程的多核系统上可用的并发性。