在函数调用中定义要由线程访问的全局 const 字符串变量

Posted

技术标签:

【中文标题】在函数调用中定义要由线程访问的全局 const 字符串变量【英文标题】:defining global const string variable to be accessed by threads in function calls 【发布时间】:2019-05-26 19:50:34 【问题描述】:

允许一个常量字符串被调用函数的各个线程全局访问。

我有以下代码,它从字符列表(允许的字母表)中选择一个随机字符并将其附加以形成一个随机单词。我将其用于遗传算法,但是当我尝试将其并行化以使其更快(家庭作业)时,它最终变得更慢。在问了我的教授并解决了大部分问题后,最后一个细节是我的字母表不允许同时读取多个线程。

我尝试定义 GENES,然后使用 #pragma omp threadprivate(GENES),这是我的教授所说的命令。

我试过了

const string GENES = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPRSTUVWXYZ"
#pragma omp threadprivate(GENES)

编译时返回这个。

error: ‘GENES’ declared ‘threadprivate’ after first use

我也试过

string GENES;
#pragma omp threadprivate(GENES)
GENES = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPRSTUVWXYZ;

返回:

error: ‘GENES’ declared ‘threadprivate’ after first use
#pragma omp threadprivate(GENES)
                             ^
error: ‘GENES’ does not name a type
GENES = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPRSTUVWXYZ 1234567890, .-;:_!\"#%&/()=?@$[]";

最后我尝试在线程中定义 GENES 并将它们作为参数传递或将它们硬编码到函数中。所有这些都会使程序变慢。

我希望程序运行得更快,但实际上它运行得更慢,从添加线程后的 0.5 秒到 1-3 秒。我查了一下,这不是因为创建线程的时间。

这应该通过使字符串可供所有线程访问来解决,但我似乎无法编译和运行我成功找到的任何解决方案。

【问题讨论】:

你能把你的字符串改成 char[] 吗? 将不得不更改一些代码,但如果它有效的话。 如果你只有一个被多个线程调用的函数,那么为什么不将它声明为静态常量变量,因为静态初始化是线程安全的,所以它应该可以工作。 我不明白声明一个 const var 私有有什么好处。只读变量没有竞争风险,您将使用(一点)更多内存,您(稍微)占用您的堆栈,您需要在创建线程时复制变量,如果您有两个线程相同的核心,您在缓存中复制相同的数据。这是一个小字符串,应该不会真正改变表演,但我真的不明白。 【参考方案1】:

我的字母表不允许同时读取多个线程。

这不是真的。

从具有多个线程的std::string读取 非常好!因为它是const,所以实际上没有线程可以写入它1。它既正确快速2

在一般的 C++ 中,const loosely implies thread-safe。保持GENES 共享,这很可能不是您的性能问题的原因。

如果您的目标是找出您的性能问题,我建议您为您的平台使用适当的性能分析工具,这些工具可以识别线程/OpenMP。如果您想询问有关如何提高程序的并行性能的问题,请确保

    包括minimal, reproducible example。这并不意味着包括您的整个程序。但是一个显示性能问题的最小版本。 分享您的具体测量结果和方法。 告诉我们您如何编译程序以及运行它的系统的规格(CPU 和内存)

1:假设没有邪恶const_casts

2:除非您将可变全局变量放在同一缓存行上,否则这似乎不太可能。

【讨论】:

早上读了这篇文章,等着向我的教授询问后才回复。正如您所提到的,它不是字符串,而是一个问题,据说是用随机数和指针解决的。尽管我能够编译上述行,但最终使用 char[] 效果更好,如 cmets 中所述。非常感谢。【参考方案2】:

感谢一位朋友,我终于用下面的代码用#pragma omp threadprivate(GENES) 编译了它:

extern const string GENES;
#pragma omp threadprivate(GENES)
const string GENES = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPRSTUVWXYZ";

【讨论】:

这是否让事情变得更快(与简单的const string GENES = ...相比)?

以上是关于在函数调用中定义要由线程访问的全局 const 字符串变量的主要内容,如果未能解决你的问题,请参考以下文章

c++ 全局静态函数的理解

全局变量和const定义是啥?

关于var let const ~

关于static/const的作用

多个线程同时调用一个函数的情况

PHP5中Static和Const关键字