多线程和单线程代码维护
Posted
技术标签:
【中文标题】多线程和单线程代码维护【英文标题】:Multithreaded and singlethreaded code maintenance 【发布时间】:2019-06-11 08:43:03 【问题描述】:我有一个应用程序,我想使用多线程(通过 OpenMP)或单线程运行。
我有一个#define MT true //if true, then multithreaded, else singlethreaded
宏,它可以在两个选项之间切换。
假设在我的单线程应用程序中,有一个数组:
int foo [5];
在多线程的情况下,(假设有 4 个线程),我不得不将上面的声明为:
int foo[4][5];
单线程情况下的函数,其声明为:
void work_on_foo(int* foo)
foo[4] = 2;
变成
void work_on_foo(int thread, int** foo)
foo[thread][4] = 2;
目前,为了处理这个代码膨胀,我正在做如下粗暴的复制:
#if MT
void work_on_foo(int thread, int** foo)
#else
void work_on_foo(int* foo)
#endif
#if MT
foo[thread][4] = 2;
#else
foo[4] = 2;
#endif
这当然很难看。有没有办法防止这种蛮力的代码维护方式?唯一的另一种方法似乎是拥有两个独立的代码库,我想避免这样做。
【问题讨论】:
在这种情况下,我使用不同的头文件来分隔代码,但仍然能够保留共享代码,然后使用配置文件生成正确的代码。 根据您的描述,在构建程序时(最大)线程数是已知的。在这种情况下,我会简单地将单线程情况视为线程数为 1 的特殊情况。交换采用thread
参数的函数的参数,使其最后一个,并为该参数提供1
的默认值。最多,您的函数只需在继续之前检查接收到的thread
值的有效性 - 无需担心实现多线程和单线程版本。
代码写错了。在编写良好的代码中,“业务逻辑”部分不应该知道它是否是多线程。如果您的主逻辑代码具有参数int thread
,那么您无论如何都会被搞砸。 IMO 问题被错误地询问,这符合XY problem。
@Tryer - 如果其中一个维度设置为 1,那么数组(可能是最大的存储用户)如何“浪费空间”????数组int x[1][4]
消耗的内存与数组int x[4]
消耗的内存相同。唯一的区别是元素的索引方式(以及用于附加维度的变量,这通常是微不足道的)。除非您使用的硬件资源非常有限(如果您使用的是 OpenMP,则几乎可以肯定不会)差异将是微不足道的。阅读“过早优化”。/
如果数组的索引为thread
的元素只被给定索引的线程使用,那么你就有一个线程本地数据。 OpenMP 对此类数据有一个明确定义的概念:被声明为static int foo [5];
,数组通过使用#pragma omp threadprivate(foo)
变为线程局部的。在本文中查看更多信息:pages.tacc.utexas.edu/~eijkhout/pcse/html/omp-data.html。
【参考方案1】:
类来处理它们怎么样? 创建具有所需接口的基类并派生两个类,一个用于单线程,一个用于多线程。如果你要改变你只需要改变你的工厂。 (看看dependency injection)
【讨论】:
让我看看。但在我看来,我仍然需要重新实现它两次——一次用于单线程,一次用于多线程。 嗯,你已经这样做了。通过使用类,您只是按类分隔它们,而不是使用#define。如果你用不同的参数调用它们,我认为你不能避免使用两个不同的函数以上是关于多线程和单线程代码维护的主要内容,如果未能解决你的问题,请参考以下文章