指针警告(并行计算)
pointer warning (Parallel computing)
我希望我的程序通过拆分 [a;b] 分成 N 个部分并使用线程进行计算。问题是我很难正确运行它,我收到以下警告:从不同大小的整数转换为指针我试图通过创建一个指针来解决它,但随后它计算非常随机(有时它只运行第一个线程或忘记运行其中一个)。这是代码的一部分,包括我的尝试:
int main(int argc, char * argv[]) {
pthread_t * threads;
int i;
int *j = &i;
p = (int) strtol (argv[1], 0, 10);
if(!(threads = (pthread_t*) malloc (p*sizeof(pthread_t)))) {
std::cout<<"Not enough memory"<<std::endl;
return -1;
}
for ( i = 0; i < p; ++i) {
if (pthread_create(threads + i, NULL, &run, (void*)j)) { //here comes a trouble
std::cout << "Cannot create thread" << std::endl;
return -1;
}
}
for ( i = 0; i < p; ++i) {
if (pthread_join( threads[i], NULL)) {
std::cout << "Waiting error" << std::endl;
return -1;
}
}
free(threads);
pthread_mutex_destroy(&mutex);
std::cout << "Integral f(x) from 0 to 1 = " << S << std::endl;
return 0;
}
我该如何解决?
第一种方法中的警告(将i
转换为void *
)是由int
和void *
之间的不同位宽引起的。很可能你的整数是 32 位,指针是 64(在 64 位构建中很常见)。 它只是告诉你你正在做一些潜在的危险(将变量分配给不同大小的指针),但由于pthread_create
等待一个void *
(它不用作真正的指针,而只是作为线程启动的传输变量),你不能改变它,它没有坏处(只要你不把它用作真正的指针,不要超过数字限制不同的位宽)
另一方面,您试图修复警告的指针方法使一切变得更糟。问题是,指针在循环中永远不会改变。
j
总是指向i
,但是 i 的内容在您的循环过程中会发生变化。当线程启动现在被调用时(已经在它自己的线程上下文中,并且可能已经在一段时间后),它会在您的主线程上下文中获取 i 的当前内容 - 这可能已经是一次甚至多次循环迭代。这可能是您观察到的"随机性"的来源,并且是一个真正的错误。
因此,您可以为编译器的警告编写(注释的)忽略杂注,也可以为 i 选择一个与指针大小匹配的大小 - 但忽略警告在您的情况下更安全,因为指针大小可能因构建而异(32/64 位)
因此,解决方案确实是:
for ( i = 0; i < p; ++i) {
// important: just an example. Pragmas and warnings vary per
// compiler, please look in your compiler's reference:
#pragma disable_bit_width_cast_warning
//i instead of j - no pointer, just a copy of i
if (pthread_create(threads + i, NULL, &run, (void*)i)) {
#pragma enable_bit_width_cast_warning
std::cout << "Cannot create thread" << std::endl;
return -1;
}
}
另一种解决方案是真正使用指针 - 但该指针必须是副本。在线程中使用后,您必须将其删除:
for ( i = 0; i < p; ++i) {
// hand over a copy of i to your thread startup.
// you'll have to cast the void* back to int* in your thread startup,
// and don't forget to delete it!
if (pthread_create(threads + i, NULL, &run, (void*) new int(i))) {
std::cout << "Cannot create thread" << std::endl;
return -1;
}
}
或者你可以 - 就像NathanOliver在评论中已经建议的那样 - 使用std::thread
,这是最好的,因为它更安全,更容易使用,更好,并且没有这个void *
问题。(恕我直言,周围总是有气味)这是一个很好的描述和示例
- 我们如何并行运行算法的 n 个实例并以有效的方式计算结果函数的平均值?
- 使用与 openmp C++并行的循环计算矩阵中每一行的最小值
- 在 Vulkan 中执行并行计算着色器?
- C++ openmp 并行计算计算错误的结果
- 使用 OpenMP 并行执行比串行执行 c++ 花费更长的时间,我计算执行时间是否正确?
- 指针警告(并行计算)
- C++:快速/并行计算两个"std::vector<double>"向量之间的L1距离
- 使用C 中的线程并行计算
- 并行计算奇偶校验
- 三任务并行计算
- 使用OpenMP C++并行计算程序的积分
- 并行计算一个大矢量的和
- 用于并行计算的C++代码优化示例
- 通过集成与OpenMP并行计算
- 并行计算--混乱的输出
- 并行计算内存访问瓶颈
- 并行计算的二次形式在RcppParallel
- 分区是一个类似生活游戏的程序,用于负载平衡的并行计算
- 使用虚幻引擎4进行并行计算
- 编译器本身使用并行计算方法运行