X 86 Chain 64とAarch64のアルゴリズム選択研究室-パート1
導入
これはTECCAです、そして、このポストでは、私はAarcha 64とx 86 Chain 64システムのいくつかの実装の向こう側に同じマシンでいろいろなアルゴリズムの相対的なパフォーマンスを比較しています.
ソースコード
総研大
Vol . hでは、処理するアルゴリズムについてのサンプルの多くは妥当であるように思われる.なぜなら、パフォーマンスの違いをより簡単に分析できるからである.
Vol 0c
Vol 1c
Vol 2c
Vol 3c
Vol 4c
Vol 5c
コード0以降のコードです.CからVol 5まで.Cパフォーマンスをテストするために使用する様々なアルゴリズムを実装します.
Volnum createsample.c
結論
この記事では、ボリュームサンプルを調整するための2、3のアルゴリズムを調べました.我々は、それぞれのアルゴリズムがどのように同じゴールを達成する彼らのアプローチで異なるかについてわかっています.次のポストでは、各プログラムのパフォーマンスがどのようにして、それを期待することを証明するベンチマークを参照してください.
これはTECCAです、そして、このポストでは、私はAarcha 64とx 86 Chain 64システムのいくつかの実装の向こう側に同じマシンでいろいろなアルゴリズムの相対的なパフォーマンスを比較しています.
ソースコード
総研大
/* This is the number of samples to be processed */
#define SAMPLES 16
/* This is the volume scaling factor to be used */
#define VOLUME 50.0 // Percent of original volume
/* Function prototype to fill an array sample of
* length sample_count with random int16_t numbers
* to simulate an audio buffer */
void vol_createsample(int16_t* sample, int32_t sample_count);
VISHは、処理されるサンプル(16)のナンバーおよび使用されるボリューム・レベル(50)を制御するVol . hでは、処理するアルゴリズムについてのサンプルの多くは妥当であるように思われる.なぜなら、パフォーマンスの違いをより簡単に分析できるからである.
Vol 0c
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "vol.h"
int16_t scale_sample(int16_t sample, int volume) {
return (int16_t) ((float) (volume/100.0) * (float) sample);
}
int main() {
int x;
int ttl=0;
// ---- Create in[] and out[] arrays
int16_t* in;
int16_t* out;
in=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
out=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
// ---- Create dummy samples in in[]
vol_createsample(in, SAMPLES);
// ---- Scale the samples from in[], placing results in out[]
for (x = 0; x < SAMPLES; x++) {
out[x]=scale_sample(in[x], VOLUME);
}
// ---- This part sums the samples
for (x = 0; x < SAMPLES; x++) {
ttl=(ttl+out[x])%1000;
}
// ---- Print the sum of the samples
printf("Result: %d\n", ttl);
return 0;
}
を参照).C、オーディオサンプルは、ボリューム・スケーリングファクターによって乗じられます.そして、サインされた16ビット整数と浮動小数点値の間に投げられます.この方法は多くの資源を必要とする.Vol 1c
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "vol.h"
int16_t scale_sample(int16_t sample, int volume) {
return ((((int32_t) sample) * ((int32_t) (32767 * volume / 100) <<1) ) >> 16);
}
int main() {
int x;
int ttl=0;
// ---- Create in[] and out[] arrays
int16_t* in;
int16_t* out;
in=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
out=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
// ---- Create dummy samples in in[]
vol_createsample(in, SAMPLES);
// ---- Scale the samples from in[], placing results in out[]
for (x = 0; x < SAMPLES; x++) {
out[x]=scale_sample(in[x], VOLUME);
}
// ---- This part sums the samples
for (x = 0; x < SAMPLES; x++) {
ttl=(ttl+out[x])%1000;
}
// ---- Print the sum of the samples
printf("Result: %d\n", ttl);
return 0;
}
Vol 1Cは固定小数点計算を利用する.これは、整数と浮動小数点の間で繰り返し鋳造するコストを回避します.Vol 2c
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "vol.h"
int main() {
int x;
int ttl=0;
// ---- Create in[] and out[] arrays
int16_t* in;
int16_t* out;
in=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
out=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
static int16_t* precalc;
// ---- Create dummy samples in in[]
vol_createsample(in, SAMPLES);
// ---- Scale the samples from in[], placing results in out[]
precalc = (int16_t*) calloc(65536,2);
if (precalc == NULL) {
printf("malloc failed!\n");
return 1;
}
for (x = -32768; x <= 32767; x++) {
precalc[(uint16_t) x] = (int16_t) ((float) x * VOLUME / 100.0);
}
for (x = 0; x < SAMPLES; x++) {
out[x]=precalc[(uint16_t) in[x]];
}
// ---- This part sums the samples
for (x = 0; x < SAMPLES; x++) {
ttl=(ttl+out[x])%1000;
}
// ---- Print the sum of the samples
printf("Result: %d\n", ttl);
return 0;
}
Vol 0とは異なり.CとVol 1.C 2、Vol 2.Cは事前にすべての65535の結果を計算します.Vol 3c
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "vol.h"
int16_t scale_sample(int16_t sample, int volume) {
return (int16_t) 100;
}
int main() {
int x;
int ttl=0;
// ---- Create in[] and out[] arrays
int16_t* in;
int16_t* out;
in=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
out=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
// ---- Create dummy samples in in[]
vol_createsample(in, SAMPLES);
// ---- Scale the samples from in[], placing results in out[]
for (x = 0; x < SAMPLES; x++) {
out[x]=scale_sample(in[x], VOLUME);
}
// ---- This part sum the samples
for (x = 0; x < SAMPLES; x++) {
ttl=(ttl+out[x])%1000;
}
// ---- Print the sum of the samples
printf("Result: %d\n", ttl);
return 0;
}
Vol 3Cは同じサンプル値を返します、このプログラムの目的は他のスケーリングボリュームアルゴリズムと比較するベースラインであるようです.Vol 4c
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "vol.h"
int main() {
#ifndef __aarch64__
printf("Wrong architecture - written for aarch64 only.\n");
#else
// these variables will also be accessed by our assembler code
int16_t* in_cursor; // input cursor
int16_t* out_cursor; // output cursor
int16_t vol_int; // volume as int16_t
int16_t* limit; // end of input array
int x; // array interator
int ttl=0 ; // array total
// ---- Create in[] and out[] arrays
int16_t* in;
int16_t* out;
in=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
out=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
// ---- Create dummy samples in in[]
vol_createsample(in, SAMPLES);
// ---- Scale the samples from in[], placing results in out[]
// set vol_int to fixed-point representation of the volume factor
vol_int = (int16_t)(VOLUME/100.0 * 32767.0);
in_cursor = in;
out_cursor = out;
limit = in + SAMPLES;
__asm__ ("dup v1.8h,%w0"::"r"(vol_int)); // duplicate vol_int into v1.8h
while ( in_cursor < limit ) {
__asm__ (
"ldr q0, [%[in_cursor]], #16 \n\t"
// load eight samples into q0 (same as v0.8h)
// from [in_cursor]
// post-increment in_cursor by 16 bytes
// ans store back into the pointer register
"sqrdmulh v0.8h, v0.8h, v1.8h \n\t"
// with 32 signed integer output,
// multiply each lane in v0 * v1 * 2
// saturate results
// store upper 16 bits of results into
// the corresponding lane in v0
"str q0, [%[out_cursor]],#16 \n\t"
// store eight samples to [out_cursor]
// post-increment out_cursor by 16 bytes
// and store back into the pointer register
: [in_cursor]"+r"(in_cursor), [out_cursor]"+r"(out_cursor)
: "r"(in_cursor),"r"(out_cursor)
: "memory"
);
}
// --------------------------------------------------------------------
for (x = 0; x < SAMPLES; x++) {
ttl=(ttl+out[x])%1000;
}
printf("Result: %d\n", ttl);
return 0;
#endif
}
Vol 4Cはインラインアセンブリを通してアクセスされるSIMD(単一の入力、複数のデータ)命令を使用します.これはAarcha 64アーキテクチャでのみ利用可能です.Vol 5c
#include <stdint.h>
#ifdef __aarch64__
#include <arm_neon.h>
#endif
#include "vol.h"
int main() {
#ifndef __aarch64__
printf("Wrong architecture - written for aarch64 only.\n");
#else
register int16_t* in_cursor asm("r20"); // input cursor (pointer)
register int16_t* out_cursor asm("r21"); // output cursor (pointer)
register int16_t vol_int asm("r22"); // volume as int16_t
int16_t* limit; // end of input array
int x; // array interator
int ttl=0; // array total
// ---- Create in[] and out[] arrays
int16_t* in;
int16_t* out;
in=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
out=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
// ---- Create dummy samples in in[]
vol_createsample(in, SAMPLES);
// ---- Scale the samples from in[], placing results in out[]
vol_int = (int16_t) (VOLUME/100.0 * 32767.0);
in_cursor = in;
out_cursor = out;
limit = in + SAMPLES ;
while ( in_cursor < limit ) {
vst1q_s16(out_cursor, vqrdmulhq_s16(vld1q_s16(in_cursor), vdupq_n_s16(vol_int)));
in_cursor += 8;
out_cursor += 8;
}
// --------------------------------------------------------------------
for (x = 0; x < SAMPLES; x++) {
ttl=(ttl+out[x])%1000;
}
printf("Result: %d\n", ttl);
return 0;
#endif
}
Vol 5C 4のようなC.また、SIMD命令を利用しますが、コンパイラに組み込まれたコンパイラは固有です.Vol 5また、CはAARC 64アーキテクチャのユニークな命令の使用のためにAarcha 64に特有です.コード0以降のコードです.CからVol 5まで.Cパフォーマンスをテストするために使用する様々なアルゴリズムを実装します.
Volnum createsample.c
#include <stdlib.h>
#include <stdint.h>
#include "vol.h"
void vol_createsample(int16_t* sample, int32_t sample_count) {
int i;
for (i=0; i<sample_count; i++) {
sample[i] = (rand()%65536)-32768;
}
return;
}
Volnum createsample.Cには、実行するアルゴリズムのダミーサンプルを作成するために使用されるVolnum CreateSample(Int 16 Count *サンプル、Int 32 Crowt SampleCountカウント)が含まれます.結論
この記事では、ボリュームサンプルを調整するための2、3のアルゴリズムを調べました.我々は、それぞれのアルゴリズムがどのように同じゴールを達成する彼らのアプローチで異なるかについてわかっています.次のポストでは、各プログラムのパフォーマンスがどのようにして、それを期待することを証明するベンチマークを参照してください.
Reference
この問題について(X 86 Chain 64とAarch64のアルゴリズム選択研究室-パート1), 我々は、より多くの情報をここで見つけました https://dev.to/pykedot/lab-5-1omiテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol