您应该使用更有效的线程安全内存管理。
应用程序可以使用malloc()
and free()
显式或隐式地存在于编译器生成的动态/可分配数组、向量化内在函数等代码中。
线程安全的malloc()
and free()
在一些libc
实现带有高同步性内部锁定引起的开销。存在用于多线程应用程序的更快的分配器。例如,在 Solaris 上,多线程应用程序应与“MT-hot”分配器链接mtmalloc
, (i.e.,链接到-lmtmalloc
to use mtmalloc
而不是默认的 libc 分配器)。glibc
,用于 Linux 和一些具有 GNU 用户空间的 OpenSolaris 和 FreeBSD 发行版,使用修改后的ptmalloc2
分配器,基于 Doug Lea 的dlmalloc
。它使用多个内存区域来实现近乎无锁的行为。它还可以配置为使用每线程竞技场,并且某些发行版(特别是 RHEL 6 及其衍生版本)启用了该功能。
static char** powerset(int argc, char* argv)
{
int i, j, bits, i_max = 1U << argc;
if (argc >= sizeof(i) * CHAR_BIT) {
fprintf(stderr, "Error: set too large\n");
exit(1);
}
omp_set_num_threads(2);
char** subsequences = malloc(i_max*sizeof(char*));
int characters = 0;
for (i = 0; i < i_max ; ++i)
{
for (bits=i; bits ; bits>>=1)
if (bits & 1)
++characters;
subsequences[i] = malloc(characters+1 * sizeof(char)*16);
characters = 0;
}
#pragma omp parallel for shared(subsequences, argv) private(j,bits)
for (i = 0; i < i_max; ++i)
{
int ssindex = 0;
for (bits = i, j=0; bits; bits >>= 1, ++j) {
if (bits & 1) {
subsequences[i][ssindex++] = argv[j] ;
}
}
subsequences[i][ssindex] = '\0';
}
return subsequences;
}
我在并行区域之前创建(并分配)所需的数据,然后进行剩余的计算。上面的版本在 24 核机器上运行 12 个线程,采用“Tempo de exeucao: 9.44 segundos”。
但是,当我尝试并行化以下代码时:
#pragma omp parallel for shared(subsequences) private(bits,characters)
for (i = 0; i < i_max ; ++i)
{
for (bits=i; bits ; bits>>=1)
if (bits & 1)
++characters;
subsequences[i] = malloc(characters+1 * sizeof(char)*16);
characters = 0;
}
它需要“执行速度:10.19 秒”
正如你所看到的malloc
并行会导致时间变慢。
最终,您会遇到每个子 malloc 都试图分配的问题(characters+1*DNA_SIZE*sizeof(char))
而不是((characters+1)*DNA_SIZE*sizeof(char))
,如果我理解您想要避免的情况,则在并行部分中不需要乘以缓存行大小的因子。
这段代码似乎也存在一些问题:
for (bits = i, j=0; bits; bits >>= 1, ++j) {
if (bits & 1) {
//char a = argv[j];
ss[ssindex++] = argv[j] ;
}
}
有了这段代码,j
有时会击中DNA_SIZE
or DNA_SIZE+1
,导致读取argv[j]
离开数组的末尾。 (另外,使用argc
and argv
因为这个函数中的参数名称有点令人困惑。)