创建数组时使用 OpenMP 时出现分段错误

2024-01-13

我在访问 for 循环内的数组时遇到分段错误。 我想做的是生成 DNA 字符串的所有子序列。

当我在 for 中创建数组时,就发生了这种情况。读了一段时间后,我发现openmp限制了堆栈大小,所以使用堆来代替会更安全。所以我更改代码以使用malloc,但问题仍然存在。

这是完整的代码:

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>

#define DNA_SIZE 26 
#define DNA "AGTC"

static char** powerset(int argc, char* argv)
{
    unsigned 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*));

    #pragma omp parallel for shared(subsequences, argv) 
    for (i = 0; i < i_max ; ++i) {
        //printf("{");
        int characters = 0;
        for (bits=i; bits ; bits>>=1)
            if (bits & 1)
                ++characters;

        //This is the line where the error is happening. 
        char *ss = malloc(characters+1 * sizeof(char)*16);//the *16 is just to save the cache lin       

        int ssindex = 0;

        for (bits = i, j=0; bits; bits >>= 1, ++j) {
            if (bits & 1) {
                //char a = argv[j];
                ss[ssindex++] = argv[j] ;
            } 
        }
        ss[ssindex] = '\0';
        subsequences[i] = ss;       
    }
    return subsequences;
}

char* getdna()
{
    int i;

    char *dna = (char *)malloc((DNA_SIZE+1) * sizeof(char));

    for(i = 0; i < DNA_SIZE; i++)
    {
        int randomDNA = rand() % 4;
        dna[i] = DNA[randomDNA];
    }

    dna[DNA_SIZE] = '\0';

    return dna;
}

void printResult(char** ss, int size)
{
    //PRINTING THE SUBSEQUENCES
    printf("SUBSEQUENCES FOUND:\r\n");
    int i;
    for(i = 0; i < size; i++)
    {
        printf("%i.\t{ %s } \r\n",i+1 , ss[i]);
        free(ss[i]);
    }
    free(ss);
}

int main(int argc, char* argv[])
{
    srand(time(NULL));
    double starttime, stoptime;
    starttime = omp_get_wtime();
    char* a = getdna();
    printf("%s\r\n", a);
    int size = pow(2, DNA_SIZE);
    printf("number of subsequences: %i\r\n", size);

    char** subsequences = powerset(DNA_SIZE, a);    
    //todo: make it optional printing to the stdout or saving to a file
    //printResult(subsequences, size);
    stoptime = omp_get_wtime();

    printf("Tempo de execucao: %3.2f segundos\n\n", stoptime-starttime);
    printf("Numero de sequencias geradas: %i\n\n", size);
    free(a);
    return 0;
}

我还尝试使 malloc 行变得至关重要#pragma omp critical这没有帮助。 我还尝试使用 -mstackrealign 进行编译,但这也不起作用。

感谢所有的帮助。


您应该使用更有效的线程安全内存管理。

应用程序可以使用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因为这个函数中的参数名称有点令人困惑。)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

创建数组时使用 OpenMP 时出现分段错误 的相关文章

  • 在 C++ 代码中转换字符串

    我正在学习 C 并开发一个项目来练习 但现在我想在代码中转换一个变量 字符串 就像这样 用户有一个包含 C 代码的文件 但我希望我的程序读取该文件并插入将其写入代码中 如下所示 include
  • 如何在 C# 中将 Json 转换为对象

    我想将 Json 转换为 C 中的对象 这里的 Json 是 值 e920ce0f e3f5 4c6f 8e3d d2fbc51990e4 如何使用 Object 问题看似愚蠢 但其实并不那么愚蠢 我没有简单的 Json 我有 IEnume
  • JavaScript 错误:MVC2 视图中的条件编译已关闭

    我试图在 MVC2 视图页面中单击时调用 JavaScript 函数 a href Select a JavaScript 函数 function SelectBenefit id code alert id alert code 这里 b
  • C# 根据当前日期传递日期时间值

    我正在尝试根据 sql server 中的两个日期获取记录 Select from table where CreatedDate between StartDate and EndDate我通过了5 12 2010 and 5 12 20
  • 测量进程消耗的 CPU 时钟

    我用 C 语言编写了一个程序 它是作为研究结果创建的程序 我想计算程序消耗的确切 CPU 周期 精确的循环次数 知道我怎样才能找到它吗 The valgrind tool cachegrind valgrind tool cachegrin
  • 保证复制省略是否适用于函数参数?

    如果我理解正确的话 从 C 17 开始 这段代码现在要求不进行任何复制 Foo myfunc void return Foo auto foo myfunc no copy 函数参数也是如此吗 下面的代码中的副本会被优化掉吗 Foo myf
  • 什么是竞争条件?

    编写多线程应用程序时 最常见的问题之一是竞争条件 我向社区提出的问题是 竞赛条件是什么 你如何检测它们 你如何处理它们 最后 如何防止它们发生 当两个或多个线程可以访问共享数据并且它们试图同时更改它时 就会出现竞争条件 由于线程调度算法可以
  • 条件类型定义

    如果我有一小段这样的代码 template
  • 在 azure blob 存储中就地创建 zip 文件

    我将文件存储在 Blob 存储帐户内的一个容器中 我需要在第二个容器中创建一个 zip 文件 其中包含第一个容器中的文件 我有一个使用辅助角色和 DotNetZip 工作的解决方案 但由于 zip 文件的大小最终可能达到 1GB 我担心在进
  • Unity c# 四元数:将 y 轴与 z 轴交换

    我需要旋转一个对象以相对于现实世界进行精确旋转 因此调用Input gyro attitude返回表示设备位置的四元数 另一方面 这迫使我根据这个四元数作为默认旋转来计算每个旋转 将某些对象设置为朝上的简单方法如下 Vector3 up I
  • 以编程方式创建 Blob 存储容器

    我有一个要求 即在创建公司时 在我的 storageaccount 中创建关联的 blob 存储容器 并将容器名称设置为传入的字符串变量 我已尝试以下操作 public void AddCompanyStorage string subDo
  • 使用 gcc 时在头文件中查找定义的好方法是什么?

    在使用 gcc 时 有人有推荐的方法在头文件中查找定义吗 使用 MSVC 时 我只需右键单击并选择 转到定义 这非常好 我使用过 netbeans gcc 它确实有代码帮助 包括到定义的超链接 所以这是一种选择 但是 我想知道是否有任何其他
  • C++ 指针引用混淆

    struct leaf int data leaf l leaf r struct leaf p void tree findparent int n int found leaf parent 这是 BST 的一段代码 我想问一下 为什么
  • C:设置变量范围内所有位的最有效方法

    让我们来int举个例子 int SetBitWithinRange const unsigned from const unsigned to To be implemented SetBitWithinRange应该返回一个int其中所有
  • 构建 C# MVC 5 站点时项目之间的处理器架构不匹配

    我收到的错误如下 2017 年 4 月 20 日构建 13 23 38 C Windows Microsoft NET Framework v4 0 30319 Microsoft Common targets 1605 5 警告 MSB3
  • Array.of 与“[ ]”。何时使用 Array.of 而不是“[ ]”?

    当我发现时我正在读一些书Array of https developer mozilla org en docs Web JavaScript Reference Global Objects Array of 根据 MDN Array o
  • 任何人都可以清楚地告诉如何在不使用像 这样的预定义函数的情况下找到带有小数值或小数值的指数吗? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 例如 2 0 5 1 414 所以想要 我是 c 的新手 所以请解释简单的逻辑 如果不是复杂的逻辑也足够了 在数学中 从整数取幂到实数
  • .Net Reactive Extensions Framework (Rx) 是否考虑拓扑顺序?

    Net 反应式扩展框架是否按拓扑顺序传播通知以最大限度地减少更新量 就像 Scala Rx 所做的那样 Net 反应式扩展 Rx 是否可以 https github com lihaoyi scala rx wiki How it Work
  • 声明一个负长度的数组

    当创建负长度数组时 C 中会发生什么 例如 int n 35 int testArray n for int i 0 i lt 10 i testArray i i 1 这段代码将编译 并且启用 Wall 时不会出现警告 并且似乎您可以分配
  • 如何在 C# 中获取 CMD/控制台编码

    我需要指定正确的代码页来使用 zip 库打包文件 正如我所见 我需要指定控制台编码 在我的例子中为 866 C Users User gt mode Status for device CON Lines 300 Columns 130 K

随机推荐