とりあえず、第2章 SIMDプログラミングの基礎を見ながらちょっと触ってみる。
2.3.2の例題プログラムをコンパイルしようとすると、
$ gcc -maltivec -mabi=altivec ex2-1.c -o ex2-1.elf
ex2-1.c: In function main:
ex2-1.c:14: error: incompatible types in assignment
なんて怒られる。(あ、ソースファイル名は変えてあります)
ソースを読んで、文脈的にvcの型が合わないんだろうと思って*をつけたらうまく動いた。
14     *vc = vec_add(*va, *vb);    // 1 + 2, 3 + 4, 5 + 6, 7 + 8
$ !gcc
gcc -maltivec -mabi=altivec ex2-1.c -o ex2-1.elf
$ ./ex2-1.elf
c[0]=3, c[1]=7, c[2]=11, c[3]=15
調子に乗って演習問題もやってみる。
演習問題 (2-1)
#include <stdio.h>
#include <altivec.h>

#define MAX_NUM 1024

int a[MAX_NUM] __attribute__((aligned(16)));
int b[4] __attribute__((aligned(16))) = {0, 0, 0, 0};

int main(int argc, char *argv[])
{
  int i;
  vector signed int *va;
  vector signed int *vb = (vector signed int *) b;

  for (i = 0; i < MAX_NUM; i++) {
    a[i] = i + 1;
  }

  for (i = 0; i < MAX_NUM; i += 4) {
    va = (vector signed int *) (a + i);
    *vb = vec_add(*va, *vb);
  }

  printf("%d\n", b[0] + b[1] + b[2] + b[3]);

  return 0;
}
模範解答が載っていないのであっているかわからない。ひょっとしたら、出題者の意図としては、1024の配列ではなく4要素の配列を作って、ループの中で4つづつ中身を書き換えさせたいのかも知れないが、これでもまあ問題はないだろう。
1024の総和だと、SIMDを使わない場合と差が出なかったので、102400で試してみたところ、SIMDを使った方が遅かった(笑)。まあ、これは使い方を覚えるためのサンプルなので、そんなものだろう。
不思議なことに、SIMDを使ったほうはほぼuser time だけを消費し、SIMDを使わない方はほぼ sys time だけを消費した。

演習問題 (2-2)
#include <stdio.h>
#include <altivec.h>

#define SIZE    (16)

unsigned short in[SIZE] __attribute__((aligned(16))) = {
  1,  2,  3,  4,  5,  6,  7,  8,
  9, 10, 11, 12, 13, 14, 15, 16
};
static unsigned short dummy[SIZE] __attribute__((aligned(16)));

float out[SIZE] __attribute__((aligned(16)));

int main(int argc, char *argv[])
{
  int i;
  vector unsigned short *va;
  vector unsigned short *vb = (vector unsigned short *)dummy;
  vector unsigned char vpat1 = (vector unsigned char) {
    0x10, 0x10, 0x00, 0x01, 0x10, 0x10, 0x02, 0x03,
    0x10, 0x10, 0x04, 0x05, 0x10, 0x10, 0x06, 0x07,
  };
  vector unsigned char vpat2 = (vector unsigned char) {
    0x10, 0x10, 0x08, 0x09, 0x10, 0x10, 0x0a, 0x0b,
    0x10, 0x10, 0x0c, 0x0d, 0x10, 0x10, 0x0e, 0x0f,
  };

  vector unsigned int vc;
  vector float *vd;

  va = (vector unsigned short *)in;

  vc = vec_perm(*va, *vb, vpat1);
  vd = (vector float *)out;
  *vd = vec_ctf(vc, 1);
  vc = vec_perm(*va, *vb, vpat2);
  vd = (vector float *)(out + 4);
  *vd = vec_ctf(vc, 1);

  va = (vector unsigned short *)(in + 8);
  vc = vec_perm(*va, *vb, vpat1);
  vd = (vector float *)(out + 8);
  *vd = vec_ctf(vc, 1);
  vc = vec_perm(*va, *vb, vpat2);
  vd = (vector float *)(out + 12);
  *vd = vec_ctf(vc, 1);

  for (i = 0; i < SIZE; i++) {
    printf("out[%02d]=%0.1f\n", i, out[i]);
  }

  return 0;
}
2-2は、最初出題プログラム2-2をコピーして始めたら、inとoutが16バイトアラインに並んでいなくてはまった。
後は、vector short と vector int の関係、メモリイメージ、vec_permの使い方が頭の中でリンクしなくて、結構はまってしまった。
長くなるので続きは次のエントリで。

カテゴリ

トラックバック(0)

このブログ記事を参照しているブログ一覧: CELLプログラミングその1

このブログ記事に対するトラックバックURL: https://www.wizard-limit.net/cgi-bin/mt/mt-tb.cgi/1113

コメントする

このブログ記事について

このページは、falseが2007年1月 1日 15:57に書いたブログ記事です。

ひとつ前のブログ記事は「PS3にFedora Core5(2)」です。

次のブログ記事は「CELLプログラミングその2」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

広告

Powered by Movable Type 6.1.1