c++ - 指针警告(并行计算)

标签 c++ parallel-processing mutex

我希望我的程序通过将 [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 之间不同的位宽度引起的>无效*。您的整数很可能是 32 位,而指针是 64 位(在 64 位版本中很常见)。 它只是告诉您,您正在做一些潜在危险的事情(将变量分配给不同大小的指针),但由于 pthread_create 等待 void * (它不使用作为真正的指针,但仅作为线程启动的传输变量),您无法更改它,并且它不会造成任何损害(只要您不将其用作真正的指针并且不超过数值)不同位宽的限制)

另一方面,您尝试修复警告的指针方法使一切变得更糟。问题是,指针在循环中永远不会改变。

j 始终指向 i,但 i 的内容在循环期间发生变化。当你的线程启动现在被调用时(已经在它自己的线程上下文中,并且可能已经过了一段时间),它会获取主线程上下文中 i 的当前内容 - 这可能已经是 1 或什至稍后进行更多循环迭代。这可能是您观察到的“随机性”的根源,并且是一个真正的错误。

因此,您可以为编译器的警告编写一个(带注释的)ignore pragma,或者您可以为 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 * 问题。 (恕我直言,类型转换周围总是有气味)这是一个不错的description and example

关于c++ - 指针警告(并行计算),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49200925/

相关文章:

c - OPENMP - 带前提条件的并行化 Schwarz 算法

amazon-ec2 - Ray 未在 EC2 上启动 worker

java - 如何仍然使用 Future.get 管理并行化?

ruby - 如何限制同一 Ruby 脚本的并发实例?

rust - 在防止死锁的同时,是否有一种工具可以在 Rust 中锁定多个互斥锁?

c++ - 使用哪个命令来执行 C++ 代码中的程序 [Linux]?

c++ - 带有指针模板参数的模板类的特化

c++ - SDL 中的 Fill_Rect

c++ - 为什么 enable_if<>* = nullptr 有效而 enable_if<> = void 无效?

c - 程序间歇性地坚持 main 报告不同的线程 id 而不是线程本身