Imported Upstream version 1.4
[deb_x265.git] / source / test / testbench.cpp
1 /*****************************************************************************
2 * Copyright (C) 2013 x265 project
3 *
4 * Authors: Gopu Govindaswamy <gopu@govindaswamy.org>
5 * Mandar Gurav <mandar@multicorewareinc.com>
6 * Mahesh Pittala <mahesh@multicorewareinc.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
21 *
22 * This program is also available under a commercial proprietary license.
23 * For more information, contact us at license @ x265.com.
24 *****************************************************************************/
25
26 #include "common.h"
27 #include "primitives.h"
28 #include "pixelharness.h"
29 #include "mbdstharness.h"
30 #include "ipfilterharness.h"
31 #include "intrapredharness.h"
32 #include "param.h"
33 #include "cpu.h"
34
35 using namespace x265;
36
37 const char* lumaPartStr[NUM_LUMA_PARTITIONS] =
38 {
39 " 4x4", " 8x8", "16x16", "32x32", "64x64",
40 " 8x4", " 4x8",
41 " 16x8", " 8x16",
42 "32x16", "16x32",
43 "64x32", "32x64",
44 "16x12", "12x16", " 16x4", " 4x16",
45 "32x24", "24x32", " 32x8", " 8x32",
46 "64x48", "48x64", "64x16", "16x64",
47 };
48
49 const char* chromaPartStr420[NUM_CHROMA_PARTITIONS] =
50 {
51 " 2x2", " 4x4", " 8x8", "16x16", "32x32",
52 " 4x2", " 2x4",
53 " 8x4", " 4x8",
54 " 16x8", " 8x16",
55 "32x16", "16x32",
56 " 8x6", " 6x8", " 8x2", " 2x8",
57 "16x12", "12x16", " 16x4", " 4x16",
58 "32x24", "24x32", " 32x8", " 8x32",
59 };
60
61 const char* chromaPartStr422[NUM_CHROMA_PARTITIONS] =
62 {
63 " 2x4", " 4x8", " 8x16", "16x32", "32x64",
64 " 4x4", " 2x8",
65 " 8x8", " 4x16",
66 "16x16", " 8x32",
67 "32x32", "16x64",
68 " 8x12", " 6x16", " 8x4", " 2x16",
69 "16x24", "12x32", " 16x8", " 4x32",
70 "32x48", "24x64", "32x16", " 8x64",
71 };
72
73 const char* const* chromaPartStr[X265_CSP_COUNT] =
74 {
75 lumaPartStr,
76 chromaPartStr420,
77 chromaPartStr422,
78 lumaPartStr
79 };
80
81 void do_help()
82 {
83 printf("x265 optimized primitive testbench\n\n");
84 printf("usage: TestBench [--cpuid CPU] [--testbench BENCH] [--help]\n\n");
85 printf(" CPU is comma separated SIMD arch list, example: SSE4,AVX\n");
86 printf(" BENCH is one of (pixel,transforms,interp,intrapred)\n\n");
87 printf("By default, the test bench will test all benches on detected CPU architectures\n");
88 printf("Options and testbench name may be truncated.\n");
89 }
90
91 PixelHarness HPixel;
92 MBDstHarness HMBDist;
93 IPFilterHarness HIPFilter;
94 IntraPredHarness HIPred;
95
96 int main(int argc, char *argv[])
97 {
98 int cpuid = x265::cpu_detect();
99 const char *testname = 0;
100
101 if (!(argc & 1))
102 {
103 do_help();
104 return 0;
105 }
106 for (int i = 1; i < argc - 1; i += 2)
107 {
108 if (strncmp(argv[i], "--", 2))
109 {
110 printf("** invalid long argument: %s\n\n", argv[i]);
111 do_help();
112 return 1;
113 }
114 const char *name = argv[i] + 2;
115 const char *value = argv[i + 1];
116 if (!strncmp(name, "cpuid", strlen(name)))
117 {
118 bool bError = false;
119 cpuid = parseCpuName(value, bError);
120 if (bError)
121 {
122 printf("Invalid CPU name: %s\n", value);
123 return 1;
124 }
125 }
126 else if (!strncmp(name, "testbench", strlen(name)))
127 {
128 testname = value;
129 printf("Testing only harnesses that match name <%s>\n", testname);
130 }
131 else
132 {
133 printf("** invalid long argument: %s\n\n", name);
134 do_help();
135 return 1;
136 }
137 }
138
139 int seed = (int)time(NULL);
140 const char *bpp[] = { "8bpp", "16bpp" };
141 printf("Using random seed %X %s\n", seed, bpp[HIGH_BIT_DEPTH]);
142 srand(seed);
143
144 // To disable classes of tests, simply comment them out in this list
145 TestHarness *harness[] =
146 {
147 &HPixel,
148 &HMBDist,
149 &HIPFilter,
150 &HIPred
151 };
152
153 EncoderPrimitives cprim;
154 memset(&cprim, 0, sizeof(EncoderPrimitives));
155 Setup_C_Primitives(cprim);
156 Setup_Alias_Primitives(cprim);
157
158 struct test_arch_t
159 {
160 char name[12];
161 int flag;
162 } test_arch[] =
163 {
164 { "SSE2", X265_CPU_SSE2 },
165 { "SSE3", X265_CPU_SSE3 },
166 { "SSSE3", X265_CPU_SSSE3 },
167 { "SSE4", X265_CPU_SSE4 },
168 { "AVX", X265_CPU_AVX },
169 { "XOP", X265_CPU_XOP },
170 { "AVX2", X265_CPU_AVX2 },
171 { "", 0 },
172 };
173
174 for (int i = 0; test_arch[i].flag; i++)
175 {
176 if (test_arch[i].flag & cpuid)
177 printf("Testing primitives: %s\n", test_arch[i].name);
178 else
179 continue;
180
181 EncoderPrimitives vecprim;
182 memset(&vecprim, 0, sizeof(vecprim));
183 Setup_Instrinsic_Primitives(vecprim, test_arch[i].flag);
184 for (size_t h = 0; h < sizeof(harness) / sizeof(TestHarness*); h++)
185 {
186 if (testname && strncmp(testname, harness[h]->getName(), strlen(testname)))
187 continue;
188 if (!harness[h]->testCorrectness(cprim, vecprim))
189 {
190 fprintf(stderr, "\nx265: intrinsic primitive has failed. Go and fix that Right Now!\n");
191 return -1;
192 }
193 }
194
195 EncoderPrimitives asmprim;
196 memset(&asmprim, 0, sizeof(asmprim));
197 Setup_Assembly_Primitives(asmprim, test_arch[i].flag);
198 memcpy(&primitives, &asmprim, sizeof(EncoderPrimitives));
199 for (size_t h = 0; h < sizeof(harness) / sizeof(TestHarness*); h++)
200 {
201 if (testname && strncmp(testname, harness[h]->getName(), strlen(testname)))
202 continue;
203 if (!harness[h]->testCorrectness(cprim, asmprim))
204 {
205 fprintf(stderr, "\nx265: asm primitive has failed. Go and fix that Right Now!\n");
206 return -1;
207 }
208 }
209 }
210
211 /******************* Cycle count for all primitives **********************/
212
213 EncoderPrimitives optprim;
214 memset(&optprim, 0, sizeof(optprim));
215 Setup_Instrinsic_Primitives(optprim, cpuid);
216 Setup_Assembly_Primitives(optprim, cpuid);
217 Setup_Alias_Primitives(optprim);
218
219 /* some hybrid primitives may rely on other primitives in the
220 * global primitive table, so set up those pointers. This is a
221 * bit ugly, but I don't see a better solution */
222 memcpy(&primitives, &optprim, sizeof(EncoderPrimitives));
223
224 printf("\nTest performance improvement with full optimizations\n");
225
226 for (size_t h = 0; h < sizeof(harness) / sizeof(TestHarness*); h++)
227 {
228 if (testname && strncmp(testname, harness[h]->getName(), strlen(testname)))
229 continue;
230 printf("== %s primitives ==\n", harness[h]->getName());
231 harness[h]->measureSpeed(cprim, optprim);
232 }
233
234 printf("\n");
235 return 0;
236 }