我使用多个pthreads来计算pi,使用在每个线程中运行的以下代码:
void *run(void *arg) {
int *index = (int *) arg; // thread number, from 0 to thread_count - 1
int i;
double *partsum = (double *)malloc(sizeof(double));
*partsum = 0.0;
for (i = *index; i < NUM_STEPS; i += thread_count) {
*partsum += 1.0 / (i * 4.0 + 1.0);
*partsum -= 1.0 / (i * 4.0 + 3.0);
}
pthread_exit((void *) partsum);
}
然后将每个线程的返回值加到变量result
并使用printf打印出来。如果我像这样使用printf,我会得到所需的输出(注意result
存储在double中):
printf("%.10f\n", result);
此外,如果我改变线程数,结果不会改变。
奇怪的是,如果我像这样使用printf,结果将取决于正在运行的线程数。我使用的线程越多越准确。
printf("%.15f\n", result);
我想出了一些可能的原因:
据我所知,如果小数点后需要超过15±2位,则不应该依赖printf输出值。但这仍然无法解释为什么最终值随线程数而变化。
它可能与sizeof(void *)有关,但如果我使用的是32位机器,这只会导致问题(它根本不允许我将double转换为void *)。
我很清楚浮点数的机器表示,但我没有提供这种行为的可行解释。
为什么printf在使用不同的线程数时会输出不同的值?
这是主要的线程代码:
int main(int argc, char **argv) {
int thread_count = atoi(argv[1]);
pthread_t *threads = (pthread_t *) malloc(sizeof(pthread_t) * thread_count);
int *args = (int *) malloc(sizeof(int) * thread_count);
for (int i = 0; i < thread_count; i++)
args[i] = i;
for (int i = 0; i < thread_count; i++) {
pthread_create(&threads[i], NULL, run, (void *) &args[i]);
}
double result = 0.0;
for (i = 0; i < thread_count; i++) {
void **value = (void **)malloc(sizeof(double *));
double **partsum;
pthread_join(threads[i], value);
partsum = (double **) value;
result += **partsum;
free(*partsum);
}
printf("%.15f\n", result);
}