“线程安全”函数是不是依赖于并行化框架?

Posted

技术标签:

【中文标题】“线程安全”函数是不是依赖于并行化框架?【英文标题】:Are "thread-safe" functions parallelization framework dependent?“线程安全”函数是否依赖于并行化框架? 【发布时间】:2018-09-19 23:32:19 【问题描述】:

我有这个简单的 MATLAB 代码,它在并行循环中调用 imregionalmax 超过 256 个 16X16 像素的路径。

function y = Parimregionalmax(x)
   assert(isa(x,'uint8'));
   assert( all(size(x)==[16 16 256]) );
   y = zeros(size(x));
   parfor k = 1:size(x,3)  
     y(:,:,k) = imregionalmax(x(:,:,k));
   end
end

将此代码提供给 MATLAB 的 Coder 会得到以下 C 代码:

/*
 * Parimregionalmax.c
 *
 * Code generation for function 'Parimregionalmax'
 *
 */

/* Include files */
#include "rt_nonfinite.h"
#include "Parimregionalmax.h"
#include "libmwimregionalmax.h"

/* Function Definitions */
void Parimregionalmax(const unsigned char x[65536], double y[65536])

  int k;
  int i0;
  int i1;
  double imSize[2];
  unsigned char varargin_1[256];
  boolean_T conn[9];//unsigned char 
  double connSize[2];
  boolean_T BW[256];

#pragma omp parallel for \
 num_threads(omp_get_max_threads()) \
 private(i0,i1) \
 firstprivate(varargin_1,imSize,conn,connSize,BW)

  for (k = 0; k < 256; k++) 
    for (i0 = 0; i0 < 16; i0++) 
      for (i1 = 0; i1 < 16; i1++) 
        varargin_1[i1 + (i0 << 4)] = x[(i1 + (i0 << 4)) + (k << 8)];
      
    

    for (i0 = 0; i0 < 2; i0++) 
      imSize[i0] = 16.0;
    

    for (i0 = 0; i0 < 9; i0++) 
      conn[i0] = true;
    

    for (i0 = 0; i0 < 2; i0++) 
      connSize[i0] = 3.0;
    

    imregionalmax_uint8(varargin_1, BW, 2.0, imSize, conn, 2.0, connSize);
    for (i0 = 0; i0 < 16; i0++) 
      for (i1 = 0; i1 < 16; i1++) 
        y[(i1 + (i0 << 4)) + (k << 8)] = BW[i1 + (i0 << 4)];
      
    
  


/* End of code generation (Parimregionalmax.c) */

如您所见,生成的代码(完美运行)使用 openmp 并行化框架并调用函数imregionalmax_uint8,该函数在单独的“黑盒”dll(带有相应的头文件和 lib 文件)中实现。

无论我使用哪种并行化框架,我是否可以假设这个函数始终是线程安全的?

示例:

1.在控制台中使用C++&lt;thread&gt;库定义两个线程可以吗 应用程序(在 VS 中也称为 exe 文件)并从每个线程调用 imregionalmax_uint8?

    做两个独立的dll(由exe文件加载)可以调用这个函数 同时?

【问题讨论】:

不,该函数不知道有关线程的 bean。就像几乎所有函数一样,它假定调用者将负责线程安全,确保在函数执行时区域数据不会更改。 #pragma omp 负责处理。函数的客户端程序员总是对线程安全负责,通常是最没有资格了解其含义的人,这是编写线程代码困难的根本原因。 @HansPassant “确保在函数执行时区域数据不能更改”是什么意思?我怎样才能确保这一点? 不要让另一个线程写入它。 #pragma omp 负责处理 【参考方案1】:

是和不是。

不,因为几乎没有人为这种事情写出好的保证。 This is a wonderful podcast about NVidia using C++'s threading model 最终将线程系统形式化,抱怨在 C++ 尝试之前,大多数抽象线程/内存模型都是废话。充其量你会得到关于一组特定硬件的非常神秘和具体的信息,或者声称你像其他一些(通常更古老的)硬件一样工作。

除了是的,因为在实践中,他们使用的互斥锁和同步等类型将在几乎所有桌面系统上兼容。移动计算 CPU 和其他更晦涩的系统可能不那么重要。

【讨论】:

以上是关于“线程安全”函数是不是依赖于并行化框架?的主要内容,如果未能解决你的问题,请参考以下文章

并行流是不是以线程安全的方式处理上游迭代器?

JNI 函数是线程安全的吗?

对于写入固定大小数组的不同部分的并行线程,是不是存在线程安全的 Java 数据结构?

纯并行添加的Java ArrayList.add() 方法线程安全吗? [复制]

C++ 无法理解为啥这段代码不是线程安全的

如何在并行 JVM 进程(不是线程)中运行 TestNG 测试