Question

Je voudrais utiliser la bibliothèque FFTW C de Delphi 2009 et selon cette documentation;

http://www.fftw.org/install/fftw_usage_from_delphi.txt

pour augmenter les performances dans la bibliothèque FFTW (telle qu'elle peut utiliser des extensions SIMD) tableaux passés en soit unique (flottant) ou double (double) doivent être alignés soit à 4 ou 8 limites d'octets. J'ai trouvé des documents parlant de l'alignement des structures d'enregistrement, mais rien de spécifique sur les tableaux. Est-il possible de le faire dans Delphi 2009.

Ainsi, le code (copié à partir de la documentation ci-dessus) ressemblerait à ceci;

var
      in, out : Array of Single; // Array aligned at 4 byte boundary
      plan : Pointer;

    {$APPTYPE CONSOLE}

    begin

      ...  

      SetLength(in, N);
      SetLength(out, N);

      plan := _fftwf_plan_dft_1d(dataLength, @in[0], @out[0],
                                 FFTW_FORWARD, FFTW_ESTIMATE);

En outre dans la documentation ci-dessus, ils parlent de 8 et les limites de 16 octets, mais il semble pour moi, il devrait être de 4 et 8 limites d'octets, le cas échéant pourrait clair que jusqu'à ce serait génial.

Merci, Bruce

Était-ce utile?

La solution

Delphi ne fournit aucun moyen pour contrôler l'alignement d'une mémoire qu'il alloue. Vous êtes de gauche soit appuyer sur le comportement documenté pour le gestionnaire de mémoire installée, ou allouer de la mémoire avec un espace de jeu, puis aligner vous-même, comme Mghie montre .

Si vous craignez que le gestionnaire de mémoire de Delphi ne fournit pas l'alignement souhaité pour les tableaux dynamiques, alors vous pouvez aller de l'avant et d'utiliser les fonctions de mémoire fournies par la DLL. La note mentionne que vous citez et _fftwf_malloc _fftwf_free, mais il donne une sorte d'avertissement que la mémoire allouée par FreeMem « ne peuvent pas être directement accessible à partir de Delphi. » Cela ne peut pas être ce que les auteurs voulaient dire, cependant, parce que c'est pas comment fonctionne la mémoire dans Windows. Les auteurs sans doute voulu dire que la mémoire allouée par ne peut pas être GetMem libéré par Delphi {$POINTERMATH ON}, et la mémoire allouée par Delphi de ne peuvent pas être ERangeError libérés par <=>. C'est rien de spécial, cependant; vous toujours besoin de garder vos fonctions de gestion de mémoire appairés.

Si vous utilisez pour obtenir votre <=> tableau, vous pouvez y accéder via un type de pointeur ordinaire. Par exemple:

var
  dataIn, dataOut: PDouble;
begin
  dataIn := _fftwf_malloc(...);
  dataOut := _fftwf_malloc(...);
  _fftwf_plan_dft_1d(dataLength, dataIn, dataOut,
                     FFTW_FORWARD, FFTW_ESTIMATE);

de Delphi 2009, vous pouvez même utiliser la syntaxe de tableau sur les pointeurs:

dataIn[0] := 3.5;
dataIn[2] := 7.3;

Pour permettre cela, utilisez la directive du compilateur <=>; il n'est pas activé par défaut, sauf pour les types de caractères pointeur.

L'inconvénient de se répartir manuellement des tableaux comme celui-ci est que vous perdez le contrôle de la plage. Si vous indexez au delà de la fin d'un tableau, vous ne serez pas facile à reconnaître plus exception <=>. Vous obtenez la mémoire corrompue, les violations d'accès, ou mystérieusement plantage des programmes à la place.

Autres conseils

Notez que vous pouvez créer des structures de données avec un alignement personnalisé que vous pourriez avoir besoin. Par exemple, pour aligner vos données FFT sur 128 limites d'octets:

procedure TForm1.Button1Click(Sender: TObject);
type
  TFFTData = array[0..63535] of double;
  PFFTData = ^TFFTData;
var
  Buffer: pointer;
  FFTDataPtr: PFFTData;
  i: integer;
const
  Alignment = 128; // needs to be power of 2
begin
  GetMem(Buffer, SizeOf(TFFTData) + Alignment);
  try
    FFTDataPtr := PFFTData((LongWord(Buffer) + Alignment - 1)
                           and not (Alignment - 1));

    // use data...
    for i := Low(TFFTData) to High(TFFTData) do
      FFTDataPtr[i] := i * pi;

  finally
    FreeMem(Buffer);
  end;
end;

Modifier

En ce qui concerne le commentaire environ deux fois la mémoire allouée: La FFTData pile variable est de type PFFTData, pas de TFFTData, il est donc un pointeur. Ce n'est pas évident en raison de l'amélioration de la syntaxe permettant d'omettre le ^ pour déréférencer le pointeur. La mémoire est allouée à GetMem (), et de travailler avec le type approprié à la place du bloc de mémoire non typée le transtypage est employé. Je devrais probablement avoir appelé FFTDataPtr.

blocs de segment de mémoire sont toujours alignés sur iirc bounderies 16 octets par FastMM (l'ancien D7 memmanager aligné à 8). Je ne sais pas ShareMem, puisque je ne l'utilise pas.

Et des tableaux dynamiques sont des structures à base de tas. tableaux Otoh dyn pourraient peut-être devenir unaligned (de 16 à 8) parce qu'il ya un nombre de longueur et ref préfixé. est d'imprimer simplement facile

ptruint (@in [0]) dans l'hexagone et de voir si la fin est 0 ou 8. (*)

Notez qu'il existe des en-têtes FFTW CPF. (Paquets / FFTW), autant que je sache il a été récemment fixé pour encore 64 bits.

Je ne suis pas au courant des directives d'alignement Stack en Delphi. Peut-être qu'ils sont automatiquement « naturellement » alignés bien.

(*) ptruint est FPC parlent d'un type entier non signé qui est sizeof (pointeur) large. cardinal sur 32 bits, QWORD sur 64 bits.

Ceci est une autre variante possible de mghie 's solution :

procedure TForm1.Button1Click(Sender: TObject);
type
  TFFTData = array [0..0] of Double;
  PFFTData = ^TFFTData;
var
  AllocatedBuffer: Pointer;
  AlignedArray: PFFTData;
  i: Integer;
const
  cFFTDataSize=63536;
begin

  GetMem(AllocatedBuffer, cFFTDataSize*SizeOf(Double) + 16);  // e.g 16 Bytes boudaries alignement

  try
    AlignedArray := PFFTData((Integer(AllocatedBuffer) and $FFFFFFF0) + 16);

    // use data...

    for i := 0 to cFFTDataSize-1 do
      AlignedArray[i] := i * Pi;
  finally
    FreeMem(AllocatedBuffer);
  end;
end;

J'ai refactorisé le morceau de code pour le rendre plus meaningfull et faire usage d'un manuel similaire alignement réparer technique.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top