FFTW和智慧的签名问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FFTW和智慧的签名问题相关的知识,希望对你有一定的参考价值。

我在Centos 7 Linux目标上使用FFTW 3.3.8。

[第一次测试,我使用FFTW执行一些计算,结果很好,并且我使用fftw_export_wisdom_to_filename保存计划。

在第二个测试中,与第一个测试相同,我刚刚在计划的计算中添加了对fftw_import_wisdom_from_filename和属性FFTW_WISDOM的调用,它也可以正常工作。

[当我在智慧文件上使用fftw-wisdom-to-conf,编译生成的输出,并将其添加到测试二进制文件中时,就会出现问题(在这种情况下,二进制文件的大小会减小,这对我来说很有趣)。

在这种情况下,导入智慧功能由于签名错误而返回“ 0”。智慧文件中的前四个md5值不正确(与预期值不同)。

如果我在智慧文件中修补这些值,则一切工作正常,可以正常导入,并且还产生FFTW。没有激活gcc优化选项,

我不使用多线程,我的配置看起来很简单,您有什么想法可以解释这种行为吗?

用于生成FFTW库的命令如下:./configure CC=gcc CFLAGS="-g" --with-slow-timer --disable-threads --disable-fortran --host=x86_64-pc-linux-gnu --prefix=/lvcugen/workspace/workspace_ext6/GR712/TMP_FFTW/INSTALL_LINUX

用于执行此测试并从test_fftw_wisdom.c安装目录编译的fftw文件的内容如下:

/*
 * P.SERAUD : FFTW Wisdom test (define MODE_USE to generate wisdom load binary, default binary generate wisdom
 *
 * Gen wisdom build command : gcc -u main -o0 -g test_fftw_wisdom.c -I ./include -L ./lib -lfftw3 -lm -lc -o test_fftw_gen_wisdom
 * Use wisdom build command : gcc -u main -o0 -g -DMODE_USE test_fftw_wisdom.c conf_wisdom.o -I ./include -L ./lib -lfftw3 -lm -lc -o test_fftw_use_wisdom
 *
 * conf_wisdom file generated by : ./bin/fftw-wisdom-to-conf < wisdom.txt
 *
 */
#include <stdio.h>
#include <string.h>

#include "fftw3.h"


/* in : input image 
 * reOut : real part (output)
 * imOut : imaginary part (output)
 * largeur : largeur des images d'entrée et de sortie
 * hauteur : idem
 */
void fourierForward(const double* in,
                    double* reOut,
                    double* imOut,
                    unsigned int largeur,
                    unsigned int hauteur)
{

/* The data is an array of type 'fftw_complex', which is by default a
   'double[2]' composed of the real ('in[i][0]') and imaginary ('in[i][1]') 
     parts of a complex number.
     */

   fftw_complex* spatial_repr;
   fftw_complex* frequency_repr;
   unsigned int i;
   fftw_plan plan;
   fftw_plan plan2;
     int resWisdom=0;

     spatial_repr= fftw_malloc(sizeof(fftw_complex)*largeur*hauteur);
   frequency_repr= fftw_malloc(sizeof(fftw_complex)*largeur*hauteur);

     fftw_set_timelimit(FFTW_NO_TIMELIMIT);

   /* Use Wisdom mode called when MODE_USE is set  */
#ifdef MODE_USE
     printf ("Importing Wisdom %d
",0);
     resWisdom = fftw_import_wisdom_from_filename("wisdom.txt");

     printf ("Import result %d
",resWisdom);

     if(resWisdom == 0)
         return;
#endif

   printf("Launching fftw_plan_dft_2d FORWARD with %d / %d
",largeur, hauteur);
     /*on calcule le plan d'exécution*/
#ifdef MODE_USE
   plan=fftw_plan_dft_2d(hauteur, largeur, spatial_repr, frequency_repr, FFTW_FORWARD, FFTW_WISDOM_ONLY | FFTW_ESTIMATE);
#else
   plan=fftw_plan_dft_2d(hauteur, largeur, spatial_repr, frequency_repr, FFTW_FORWARD, FFTW_ESTIMATE);
#endif

     if (plan == NULL)
        { 
    printf("NULL plan generated by fftw_plan_dft_2d with %d / %d !!!
",largeur, hauteur);
        return;
        }

   /*On remplit la structure qui sera utilisée par fftw*/
   for(i=0;i<largeur*hauteur;i++)
   {
          spatial_repr[i][0] = in[i]; /* real part */
      spatial_repr[i][1] =  0.0;  /* imaginary part */
      frequency_repr[i][0] =  0.0;  /* real part */
      frequency_repr[i][1] =  0.0;  /* imaginary part */
   }

     printf("Executing fftw_execute with %d / %d

",largeur, hauteur);

   /*on effectue la transformée de Fourier*/
   fftw_execute(plan);


   /*on retranscrit le résultat en 2 images, l'une représentant la partie réelle, l'autre
     la partie imaginaire*/
   for(i=0;i<largeur*hauteur;i++)
      {
          reOut[i]=frequency_repr[i][0];
          imOut[i]=frequency_repr[i][1];
                    printf("%d : in (%lf) / reOut (%lf) / imOut (%lf) 
",i, in[i],reOut[i],imOut[i]);
            }

   printf("Launching fftw_plan_dft_2d BACKWARD with %d / %d
",largeur, hauteur);
#ifdef MODE_USE
   plan2=fftw_plan_dft_2d(hauteur, largeur, spatial_repr, frequency_repr, FFTW_BACKWARD, FFTW_WISDOM_ONLY | FFTW_ESTIMATE);
#else
   plan2=fftw_plan_dft_2d(hauteur, largeur, spatial_repr, frequency_repr, FFTW_BACKWARD, FFTW_ESTIMATE);
#endif

     if (plan2 == NULL)
        { 
    printf("NULL plan generated by fftw_plan_dft_2d with %d / %d !!!
",largeur, hauteur);
        return;
        }

   /*On remplit la structure qui sera utilisée par fftw*/
   for(i=0;i<largeur*hauteur;i++)
   {
     spatial_repr[i][0] = reOut[i]; /* real part */
     spatial_repr[i][1] = imOut[i]; /* imaginary part */
     frequency_repr[i][0] =  0.0;  /* real part */
     frequency_repr[i][1] =  0.0;  /* imaginary part */
   }

     printf("Executing fftw_execute with %d / %d

",largeur, hauteur);
   /*on effectue la transformée de Fourier*/
   fftw_execute(plan2);

   /*on retrouve la matrice d'origine dans la partie réelle en la divisant par "largeur * hauteur" */ 
   for(i=0;i<largeur*hauteur;i++)
      {
          reOut[i]=frequency_repr[i][0] /(largeur*hauteur);
          imOut[i]=frequency_repr[i][1];
                    printf("%d : in (%lf) / reOut (%lf) / imOut (%lf) 
",i, in[i],reOut[i],imOut[i]);
            }

#ifndef MODE_USE
     resWisdom = fftw_export_wisdom_to_filename("wisdom.txt"); 
     printf ("Wisdom export res = %d
", resWisdom);
#endif

   /*on détruit les objets*/
   fftw_destroy_plan(plan);
   fftw_destroy_plan(plan2);
   fftw_free(spatial_repr);
   fftw_free(frequency_repr);

}

int main(void) 
{
        printf("Starting !!!!
");

        double in [8][8] =    {{0.0, 0.0,   0.0,   0.0,   0.0, 0.0, 0.0, 0.0},
            {0.0, 0.0,  70.0,  80.0,  90.0, 0.0, 0.0, 0.0},
            {0.0, 0.0,  90.0, 100.0, 110.0, 0.0, 0.0, 0.0},
            {0.0, 0.0, 110.0, 120.0, 130.0, 0.0, 0.0, 0.0},
            {0.0, 0.0, 130.0, 140.0, 150.0, 0.0, 0.0, 0.0},
            {0.0, 0.0,   0.0,   0.0,   0.0, 0.0, 0.0, 0.0},
            {0.0, 0.0,   0.0,   0.0,   0.0, 0.0, 0.0, 0.0},
            {0.0, 0.0,   0.0,   0.0,   0.0, 0.0, 0.0, 0.0}};

        double reOut [8][8] = {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
            {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
            {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
            {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
            {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
            {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
            {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
            {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}};

        double imOut [8][8] = {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
            {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
            {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
            {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
            {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
            {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
            {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
            {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}};

        fourierForward(&in[0][0], &reOut[0][0], &imOut[0][0], 8, 8);

        return 0;
}

conf_wisdom.o可执行文件中包含的test_fftw_use_wisdom目标文件是通过conf_wisdom.c编译gcc -c conf_wisdom.c源文件的结果。该源文件的内容如下:

/* Automatically generated by fftw-wisdom-to-conf from fftw 3.3.8.
   DO NOT EDIT!  (Unless you really, really want to.  Then it's okay.) */
void fftw_configure_planner(void *plnr)
{
    struct solvtab_s { void (*reg)(void *); const char *reg_nam; };
    extern void fftw_solvtab_exec(const struct solvtab_s s[], void *);

#define DECLARE(name) extern void name(void *);
#define STRINGIZEx(x) #x
#define STRINGIZE(x) STRINGIZEx(x)
#define SOLVTAB(s) { s, STRINGIZE(s) },
#define DO(X) 
    X(fftw_codelet_n1_8)
    X(fftw_dft_rank_geq2_register)
    /* end DO(X) */

    DO(DECLARE)

    const struct solvtab_s s[] = {
        DO(SOLVTAB)
        { 0, 0 }
    };

    fftw_solvtab_exec(s, plnr);
}

通过调用函数fftw_export_wisdom_to_filename生成的witness.txt文件的内容如下:

(fftw-3.3.8 fftw_wisdom #x4be12fff #x7b2df9b2 #xa5975329 #x385b0041
  (fftw_codelet_n1_8 0 #x31bff #x31bff #x0 #x2874cdd9 #x63ab3b26 #xcb8c1374 #xedc69a82)
  (fftw_codelet_n1_8 0 #x31bff #x31bff #x0 #x4e583e34 #x14aedc27 #x54a2fad7 #xd124b261)
  (fftw_dft_rank_geq2_register 0 #x31bff #x31bff #x0 #xcd87e2bd #x8b6dd8ee #x2d70ed77 #xd20ea4af)
  (fftw_codelet_n1_8 0 #x31bff #x31bff #x0 #xece23a64 #x64207145 #x3f794c2c #x32ef2fbf)
  (fftw_dft_rank_geq2_register 0 #x31bff #x31bff #x0 #xd416e586 #xdc5a4e14 #x2b04907f #x69b22bd8)
  (fftw_codelet_n1_8 0 #x31bff #x31bff #x0 #x155aa639 #x5f99241d #x6351b1a0 #xc7ccb78d)
)

未成功检查的错误md5值是#x4be12fff#x7b2df9b2#xa5975329#x385b0041。如果将这些值替换为期望的值,则一切正常。

此外,当库的全部内容包含在test_fftw_use_wisdom二进制文件中(不使用conf_wisdom.o文件)时,它也可以正常工作。

实际上,问题出在导入和导出功能都使用的功能signature_of_configuration中。当包含conf_wisdom.o时,就完整列表而言,planner内容(与nslvdescslvdescsiz关联的解析器列表)的内容将减少,并且关联的md5值必须有所不同。

答案

测试表明,当从智慧数据生成的wisdom.c既包含在导入程序中,又包含在导出程序中时,导入就起作用了。当两个程序中均不包含wisdom.c时,它也适用。如果将它包含在导入程序中但不包含在导出程序中,则它将失败。

因此,解决方法是在不使用wisdom.c的情况下构建导出程序,导出智慧,生成wisdom.c,使用wisdom.c重建导出程序,重新导出智慧,然后使用wisdom.c生成导入程序。

这似乎是FFTW的缺陷,可能在校验和检查的设计中。

以上是关于FFTW和智慧的签名问题的主要内容,如果未能解决你的问题,请参考以下文章

FFTW 函数 n2fv_64

在 Linux 和 Eclipse IDE 中使用 FFTW 库的问题

FFTW:信号由IFFT后的噪声组成

用 C++ 绘制图像的光谱(fftw,OpenCV)

FFTW 从 numpy.fft 产生不同的结果

在 C/C++ 中使用 JACK 和 fftw 的音频频谱