Hallide

You might also like

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 35

Halide

​Hexagon LLVM & Halide Compiler Team


​Qualcomm Innovation Center, Inc
​14th Jan 2022
Agenda

1Halide – An
2The Halide
3
Halide for HVX
Introduction Programming
Language

2
Halide
A new DSL for image processing and computational photography

• Fast image-processing pipelines are difficult to write


• Definition of the stages of the pipeline
• Optimization of the pipeline - vectorization, multi-threading, tiling,
etc
• Traditional languages make expression of parallelism, tiling and other
optimizations difficult
• Solution: Halide enables rapid authoring and evaluation of optimized Sobel edge detection
pipelines by separating the algorithm from the computational
organization of the different stages of the pipeline (schedule)
• Programmer defines both, the algorithm and the schedule
• Front end embedded in C++

3
Halide
A new DSL for image processing and computational photography.
• Halide programs / pipelines consist of two major components
• Algorithm
• Schedule
• Algorithm specifies what will be computed at a pixel
• Schedules specifies how the computation will be organized

​ // Image with 8 bits per pixel.


​ ImageParam input(UInt(8), 2);
​ // A pipeline stage
​ Halide::Func f;

​ // horizontal blur – Algorithm.


​ f(x, y) = (input(x-1, y) + input(x, y) + input(x+1, y))/3;
​ // Schedule
​ f.vectorize(x, 128).parallel(y, 16);

4
Halide
Typical Optimization Techniques for Image Processing

Blue boxes
represent memory
read and yellow
represent memory
written

Baseline case – compute the producer fully before


computing the consumer. Poor Cache Locality

Images courtesy halide-lang.org.


Best viewed in Slideshow mode
to enable animation. 5
Halide
Typical Optimization Techniques for Image Processing (tiling)

Tile the computation of the consumer so that the values of


the producer needed for subsequent rows of the consumer
are still in cache. Better cache utilization
Images courtesy halide-lang.org.
Best viewed in Slideshow mode
to enable animation. 6
Halide
Typical Optimization Techniques for Image Processing (tiling, vectorization &
parallelization)

Tile the computation of the consumer and vectorize the


horizontal dimension of the tiles. Divide the rows of the
consumer to be computed by 4 threads
Images courtesy halide-lang.org.
Best viewed in Slideshow mode
to enable animation. 7
Halide
Scheduling for performance (Halide vs C++ comparison)
​ // horizontal blur – Algorithm. ​for (y = min_row; y < max_row; ++y) {
​ f(x, y) = (input(x-1, y) + input(x, y) + ​ for (x = min_col, x <= max_col; ++x) {
​ input(x+1, y))/3; ​ f(x, y) =
​ (input(x-1,y) + input(x, y) + input(x+1, y)) / 3;
​ }
​}

8
Halide
Scheduling for performance (Halide vs C++ comparison)
​ // horizontal blur – Algorithm. ​for (y = min_row; y < max_row; ++y) {
​ f(x, y) = (input(x-1, y) + input(x, y) + ​ for (x = min_col, x <= max_col; ++x) {
​ input(x+1, y))/3; ​ f(x, y) =
​ (input(x-1,y) + input(x, y) + input(x+1, y)) / 3;
​ }
​}

Tiling
​f.tile(x, y, xi, yi, 128, 4); ​for (y = min_row; y < max_row/4; ++y) {
​ for (x = min_col, x <= max_col/128; ++x) {
​ for(yi = 0; yi < 4; ++yi) {
​ for (xi = 0; xi < 128; ++xi) {
​ x_ = x*128 + xi;
​ y_ = y*4 + yi;
​ f(x_, y_) = (input(x_-1,y_) + input(x_, y_) +
​ input(x_+1, y_)) / 3;
​ }
​ }
​}

9
Halide
Scheduling for performance (Halide vs C++ comparison)
Tiling & unrolling
​f.tile(x, y, xi, yi, 128, 4) ​for(y = min_row; y < max_row/4; ++y) {
​.unroll(yi); ​ for (x = min_col, x <= max_col/128; ++x) {
​ for (xi = 0; xi < 128; ++xi) {
​ x_ = x*128 + xi;
​ y_ = y*4 + 0;
​ f(x_, y_) = (input(x_-1,y_) + input(x_, y_) +
​ input(x_+1, y_)) / 3;
​ }
​ for (xi = 0; xi < 128; ++xi) {
• Benefits of unrolling ​ x_ = x*128 + xi;
​ y_ = y*4 + 1;
• Reduces branching overhead ​ f(x_, y_) = (input(x_-1,y_) + input(x_, y_) +
​ input(x_+1, y_)) / 3;
​ }
• Increases Instruction Level Parallelism ​ for (xi = 0; xi < 128; ++xi) {
(ILP) which is especially advantageous ​ x_ = x*128 + xi;
​ y_ = y*4 + 2;
on a processor like Hexagon which is a ​ f(x_, y_) = (input(x_-1,y_) + input(x_, y_) +
VLIW processor (think packets!) ​ input(x_+1, y_)) / 3;
​ }
• Exposes dependences across loop ​ for (xi = 0; xi < 128; ++xi) {
​ x_ = x*128 + xi;
iterations such as read-after-write ​ y_ = y*4 + 3;
(RAW) dependences across two ​ f(x_, y_) = (input(x_-1,y_) + input(x_, y_) +
​ input(x_+1, y_)) / 3;
iterations of a loop ​ }
10
​}
Halide
Scheduling for performance (Halide vs C++ comparison)
Tiling, unrolling and vectorization
​f.tile(x, y, xi, yi, 128, 4) ​for(y = min_row; y < max_row/4; ++y) {
​.unroll(yi) ​ for (x = min_col, x <= max_col/128; ++x) {
​ for (xi = 0; xi < 128; ++xi) {
​.vectorize(xi); ​ x_ = x*128 + xi;
​ y_ = y*4 + 0;
​ f(x_, y_) = (input(x_-1,y_) + input(x_, y_) +
​ input(x_+1, y_)) / 3;
​ }
​for (xi = 0; xi < 128; ++xi) {
​ x_ = x*128 + xi;
​ y_ = y*4 + 1;
​ f(x_, y_) = (input(x_-1,y_) + input(x_, y_) +

Not possible without
input(x_+1, y_)) / 3;
an auto-vectorizer
​ }
​for (xi = 0; xi < 128; ++xi) {
​ x_ = x*128 + xi;
​ y_ = y*4 + 2;
​ f(x_, y_) = (input(x_-1,y_) + input(x_, y_) +
​ input(x_+1, y_)) / 3;
​ }
​for (xi = 0; xi < 128; ++xi) {
​ x_ = x*128 + xi;
​ y_ = y*4 + 3;
​ f(x_, y_) = (input(x_-1,y_) + input(x_, y_) +
​ input(x_+1, y_)) / 3;
​ }
11
​}
Halide
Scheduling for performance (Halide vs C++ comparison)
Tiling, unrolling and vectorization
​f.tile(x, y, xi, yi, 128, 4) ​for(y = min_row; y < max_row/4; ++y) {
​.unroll(yi) ​ for (x = min_col, x <= max_col/128; ++x) {
​ for (xi = 0; xi < 128; ++xi) {
​.vectorizer(xi); ​ x_ = x*128 + xi;
​ y_ = y*4 + 0;
​ f(x_, y_) = (input(x_-1,y_) + input(x_, y_) +
​ input(x_+1, y_)) / 3;
​ }
​for (xi = 0; xi < 128; ++xi) {
​ x_ = x*128 + xi;
​ y_ = y*4 + 1;
Halide provides many more scheduling ​ f(x_, y_) = (input(x_-1,y_) + input(x_, y_) +
Not possible without an auto-vectorizer
​ input(x_+1, y_)) / 3;
directives for greater control over the ​ }
organization of computation. The Halide ​for (xi = 0; xi < 128; ++xi) {
​ x_ = x*128 + xi;
user guide and the tutorials hosted at ​ y_ = y*4 + 2;
​ f(x_, y_) = (input(x_-1,y_) + input(x_, y_) +
halide-lang.org are the best ​ input(x_+1, y_)) / 3;
​ }
resources for learning more about these ​for (xi = 0; xi < 128; ++xi) {
scheduling directives ​ x_ = x*128 + xi;
​ y_ = y*4 + 3;
​ f(x_, y_) = (input(x_-1,y_) + input(x_, y_) +
​ input(x_+1, y_)) / 3;
​ }
12
​}
Halide
Summary

• Halide programs consist of two major components:


◦ Algorithm
◦ Schedule
• The separation between algorithm and schedule is key. It enables:
◦ Authoring an algorithm without the complexity of computational organization
◦ Tuning and experimenting with the computational organization to achieve high
performance
• Generation of highly optimized compiled code
• The compiler is guided by the programmer explicitly specifying high-level
optimizations

13
Scheduling a Stage (1)
Reordering Dimensions (slide 1)
• Change loop orders
1 2 3
• Order is defined from innermost to
outermost loop 4 5 6
7 8 9

• Usage:
.reorder(y, x)
output.reorder(dimensions from
innermost -> outermost)
1 4 7
2 5 8
3 6 9

14
Scheduling a Stage (2)
Reordering Dimensions (slide 2)

reorder(y, x)

Row Major Column Major


Traversal Traversal

*Images, animations and pipeline credits: Halide-lang.org 15


Scheduling a Stage (6)
Tiling (slide 1)

.split(x, xo, xi, split_factor)


.split(y, yo, yi, split_factor)

.reorder(xi, yi, xo, yo)

16
Scheduling a Stage (7)
Tiling (slide 2)

1 2
Iterates over the tiles
xo
xi 3 4
1 2 5 6
3 4 7 8
yi 9 10 13 14
yo 11 12 15 16
1 2
.tile(x, y, xi, yi, 2, 2) 3 4 Iterates inside the tile

*Images, animations and pipeline credits: Halide-lang.org 17


Scheduling a Stage (8)
Vectorize
• Essentially a split and vectorize
• SIMD instruction set not used until we specify
.vectorize() directive to the stage
• Usage:
output.vectorize(x, split_factor, .vectorize(x, 128)
TailStrategy)

1 2
3 4
5 6
7 8

*Images, animations and pipeline credits: Halide-lang.org 18


Scheduling a Stage (10)
.hexagon()
• Marks the outermost loop
• All stages computed inside the Hexagon
marked loop are scheduled on Hexagon
• No manual RPC calls to setup data and
offload pipeline required .hexagon()
• Example targets:
◦ Host-HVX [where host is x86]
◦ Arm-HVX
◦ Hexagon-HVX
• Usage:
output.hexagon()
19
Scheduling a Stage (11)
Parallel
• Parallelize dimensions across threads
• A work queue created at the loop position
• Threads consume from this queue until
completion
• Usage: .parallel(y)

output.parallel(y, work_per_thread)

1 2 3 4

Parallel 1 2 3 4
threads 1 2 3 4
1 2 3 4
20
Interleaving Stages (1)
Producer Consumer Relationship
• Consider the Halide pipeline: (skipping obvious details)

• Consumer feeds on producer values

21
Interleaving Stages (2)
Compute Inline
• Calculate the producer as and when required by the consumer
• Directly replace the producer expression with it’s value
• By default all stages are inlined

22
Interleaving Stages (3)
producer_buffer is a
Compute Root Halide created
intermediate buffer
• Calculate entire producer before starting
consumer
• Usage:
producer.compute_root()

*Images, animations and pipeline credits: Halide-lang.org 23


Interleaving Stages (4)
Inline vs. Root

Compute inline Compute root


Calculate the producer as and when required Calculate all the producer before calculating
by the consumer any consumer

No additional space requirement Requires extra space

Best locality Poor locality

Lots of redundant calculations No redundant calculations

Good for simple stages with less data reuse Good for complex producer function or if
multiple consumers consume the values

24
Interleaving Stages (5)
.compute_at (slide 1)
• Place the computation of producer inside specified loop level of consumer
• Usage: producer.compute_at(consumer, y)

25
Interleaving Stages (6)
.compute_at (slide 2)
• producer.compute_at(consumer, y);
• Locality: compute_root < compute_at(consumer, y) < inline
• Redundant Computations: compute_root < compute_at(consumer, y) < inline
Bad Average Good

*Images, animations and pipeline credits: Halide-lang.org 26


Interleaving Stages (7)
.store_at / store_root
• Place the buffer at specified loop level
• By default, storage allocated just before the outermost loop of the stage
• Usage: producer.store_at(consumer, y), producer.store_root()

*Images, animations and pipeline credits: Halide-lang.org 27


Halide on Hexagon with HVX
The need for Halide

• HVX has a large number of Instructions


(650+)
• HVX architected for image processing
• Complex and distinct DSP flavor
◦ Sliding window multiplications
◦ Widening multiply accumulate instructions
◦ Vector look up table

Perform a 3-element sliding window pattern operation consisting of a


two multiplies with an additional accumulation. Data elements are
stored in the vector register pair Vuu, and coefficients in the scalar
register Rt
28
Halide on Hexagon with HVX
The need for Halide: Programming HVX - 3x3 Convolution Filter in Intrinsics
31 static void conv3x3Per2Row(
48 HVX_Vector sSum20L, sSum31L, sSum20H, sSum31H; 76 sline164 = *iptr1++; 98
49 77 sline264 = *iptr2++; 99
32 unsigned char *restrict inp,
HVX_Vector sOut01, sOut01p, sOut11, sOut11p, sOut00, s 78 sline364 = *iptr3++; sSum31L = Q6_Vh_vasr_VwVwR_sat(Q6_V_hi_W(dSu
33 int stride, Out10; 79 m031),Q6_V_lo_W(dSum031),shift);
50 80 sline004 = Q6_V_valign_VVI(sline064,sline000,4); 100
34 int width, 51 HVX_VectorPair dline000,dline100, dline200,dline300; sSum20L = Q6_Vh_vasr_VwVwR_sat(Q6_V_hi_W(dSu
81 sline104 = Q6_V_valign_VVI(sline164,sline100,4);
52 m020),Q6_V_lo_W(dSum020),shift);
82 sline204 = Q6_V_valign_VVI(sline264,sline200,4);
35 signed char *restrict mask, HVX_VectorPair dSum020, dSum031, dSum120, dSum131; 101
83 sline304 = Q6_V_valign_VVI(sline364,sline300,4);
53 sOut01 = Q6_Vub_vsat_VhVh(sSum31L,sSum20L);
36 int shift, 84
54 __m2m1m0 = mask4[0]; 102 sOut00 = Q6_V_vlalign_VVI(sOut01,sOut01p,1);
85 dline000 = Q6_W_vcombine_VV(sline004, sline000);
55 __m5m4m3 = mask4[1]; 103 *optr0++ = sOut00;
37 unsigned char *restrict outp 86 dline100 = Q6_W_vcombine_VV(sline104, sline100);
56 __m8m7m6 = mask4[2]; 104
87 dline200 = Q6_W_vcombine_VV(sline204, sline200);
38 ) 57 105
88 dline300 = Q6_W_vcombine_VV(sline304, sline300); dSum120 = Q6_Ww_vrmpy_WubRbI(dline100,__m2m1
58 HVX_Vector *iptr0 = (HVX_Vector *)(inp - 1*stride);
39 { 89 m0, 0);
HVX_Vector *iptr1 = (HVX_Vector *)(inp + 0*stride);
90 dSum020 = Q6_Ww_vrmpy_WubRbI(dline000| 106
40 int i; 60 HVX_Vector *iptr2 = (HVX_Vector *)(inp + 1*stride); ,__m2m1m0, 0); dSum131 = Q6_Ww_vrmpy_WubRbI(dline100,__m2m1
61 HVX_Vector *iptr3 = (HVX_Vector *)(inp + 2*stride); 91 dSum031 = Q6_Ww_vrmpy_WubRbI(dline000 m0, 1);
41 62 HVX_Vector *optr0 = (HVX_Vector *)(outp + 0*stride); ,__m2m1m0, 1); 107
HEXAGON_Vect32 __m2m1m0, __m5m4m3, __m8m 63 HVX_Vector *optr1 = (HVX_Vector *)(outp + 1*stride); 92 108
7m6;
64 93 dSum020 = Q6_Ww_vrmpyacc_WwWubRbI( dSum120 = Q6_Ww_vrmpyacc_WwWubRbI(dSum120,
42 65 sline000 = *iptr0++; dSum020, dline100,__m5m4m3, 0); dline200,__m5m4m3, 0);
HEXAGON_Vect32 *mask4 = (HEXAGON_Vect32 *)m 66 sline100 = *iptr1++; 94 109
ask; 67 sline200 = *iptr2++; dSum031 = Q6_Ww_vrmpyacc_WwWubRbI(dSum031, d dSum131 = Q6_Ww_vrmpyacc_WwWubRbI(dSum131,
68 sline300 = *iptr3++; line100,__m5m4m3, 1); dline200,__m5m4m3, 1);
43 95 110
69
70 sOut01p = Q6_V_vzero(); 111
44 HVX_Vector sline000,sline004,sline064;
96 dSum120 = Q6_Ww_vrmpyacc_WwWubRbI(dSum120,
71 sOut11p = Q6_V_vzero();
dSum020 = Q6_Ww_vrmpyacc_WwWubRbI(dSum020, d dline300,__m8m7m6, 0);
45 HVX_Vector sline100,sline104,sline164; 72
line200,__m8m7m6, 0); 112
73 for ( i=width; i>0; i-=VLEN )
46 HVX_Vector sline200,sline204,sline264; 97 dSum131 = Q6_Ww_vrmpyacc_WwWubRbI(dSum131,
74 { 29
dSum031 = Q6_Ww_vrmpyacc_WwWubRbI(dSum031, d dline300,__m8m7m6, 1);
75 sline064 = *iptr0++; line200,__m8m7m6, 1);
47 HVX_Vector sline300,sline304,sline364; 113
Halide on Hexagon with HVX
The need for Halide: Programming HVX - 3x3 Convolution Filter in Intrinsics
31 static void conv3x3Per2Row(
48 HVX_Vector sSum20L, sSum31L, sSum20H, sSum31H; 76 sline164 = *iptr1++; 98
49 77 sline264 = *iptr2++; 99
32 unsigned char *restrict inp,
HVX_Vector sOut01, sOut01p, sOut11, sOut11p, sOut00, s 78 sline364 = *iptr3++; sSum31L = Q6_Vh_vasr_VwVwR_sat(Q6_V_hi_W(dSu
33 int stride, Out10; 79 m031),Q6_V_lo_W(dSum031),shift);
100

Simple filter: 3x3 convolution


50 80 sline004 = Q6_V_valign_VVI(sline064,sline000,4);
34 int width, 51 HVX_VectorPair dline000,dline100, dline200,dline300; sSum20L = Q6_Vh_vasr_VwVwR_sat(Q6_V_hi_W(dSu
81 sline104 = Q6_V_valign_VVI(sline164,sline100,4);
52 m020),Q6_V_lo_W(dSum020),shift);
82 sline204 = Q6_V_valign_VVI(sline264,sline200,4);
35 signed char *restrict mask, HVX_VectorPair dSum020, dSum031, dSum120, dSum131; 101

130 lines of highly optimized HVX intrinsics


83 sline304 = Q6_V_valign_VVI(sline364,sline300,4);
53 sOut01 = Q6_Vub_vsat_VhVh(sSum31L,sSum20L);
36 int shift, 84
54 __m2m1m0 = mask4[0]; 102 sOut00 = Q6_V_vlalign_VVI(sOut01,sOut01p,1);
85 dline000 = Q6_W_vcombine_VV(sline004, sline000);
103 *optr0++ = sOut00;

Very high level of expertise required


37 unsigned char *restrict outp 55 __m5m4m3 = mask4[1];
86 dline100 = Q6_W_vcombine_VV(sline104, sline100);
56 __m8m7m6 = mask4[2]; 104
87 dline200 = Q6_W_vcombine_VV(sline204, sline200);
38 ) 57 105
88 dline300 = Q6_W_vcombine_VV(sline304, sline300); dSum120 = Q6_Ww_vrmpy_WubRbI(dline100,__m2m1
58 HVX_Vector *iptr0 = (HVX_Vector *)(inp - 1*stride);
39 { 89 m0, 0);
HVX_Vector *iptr1 = (HVX_Vector *)(inp + 0*stride);
90 dSum020 = Q6_Ww_vrmpy_WubRbI(dline000| 106
40 int i; 60 HVX_Vector *iptr2 = (HVX_Vector *)(inp + 1*stride); ,__m2m1m0, 0); dSum131 = Q6_Ww_vrmpy_WubRbI(dline100,__m2m1
61 HVX_Vector *iptr3 = (HVX_Vector *)(inp + 2*stride); 91 dSum031 = Q6_Ww_vrmpy_WubRbI(dline000 m0, 1);
41 62 HVX_Vector *optr0 = (HVX_Vector *)(outp + 0*stride); ,__m2m1m0, 1); 107
HEXAGON_Vect32 __m2m1m0, __m5m4m3, __m8m 63 HVX_Vector *optr1 = (HVX_Vector *)(outp + 1*stride); 92 108
7m6;
64 93 dSum020 = Q6_Ww_vrmpyacc_WwWubRbI( dSum120 = Q6_Ww_vrmpyacc_WwWubRbI(dSum120,
42
Higher abstraction level, but still requires
HEXAGON_Vect32 *mask4 = (HEXAGON_Vect32 *)m
ask;
65
66
67
sline000 = *iptr0++;
sline100 = *iptr1++;
sline200 = *iptr2++;
94
dSum020, dline100,__m5m4m3, 0);

dSum031 = Q6_Ww_vrmpyacc_WwWubRbI(dSum031, d
109
dline200,__m5m4m3, 0);

dSum131 = Q6_Ww_vrmpyacc_WwWubRbI(dSum131,

43
deep knowledge of HVX architecture and
68
69
70
sline300 = *iptr3++;

sOut01p = Q6_V_vzero();
line100,__m5m4m3, 1);
95
dline200,__m5m4m3, 1);
110
111

microarchitecture
44 HVX_Vector sline000,sline004,sline064;
96 dSum120 = Q6_Ww_vrmpyacc_WwWubRbI(dSum120,
71 sOut11p = Q6_V_vzero();
dSum020 = Q6_Ww_vrmpyacc_WwWubRbI(dSum020, d dline300,__m8m7m6, 0);
45 HVX_Vector sline100,sline104,sline164; 72
line200,__m8m7m6, 0); 112
73 for ( i=width; i>0; i-=VLEN )
46 HVX_Vector sline200,sline204,sline264; 97 dSum131 = Q6_Ww_vrmpyacc_WwWubRbI(dSum131,
74 { 30
dSum031 = Q6_Ww_vrmpyacc_WwWubRbI(dSum031, d dline300,__m8m7m6, 1);
75 sline064 = *iptr0++; line200,__m8m7m6, 1);
47 HVX_Vector sline300,sline304,sline364; 113
Halide on Hexagon with HVX
3x3 convolution: Halide vs HVX Intrinsics
Halide HVX Intrinsics
0.109 cycles/pixel
0.114 cycles/pixel

Algorithm
Hand-optimized,
complex loop nest

Schedule

• Halide version: 14 lines


• Very concise, easy to maintain
• Developers can quickly restructure schedule to
optimize the algorithm
• Corresponding optimization in intrinsics version
can be extremely complex
31
…94 more lines of HVX intrinsics code not shown
Halide on Hexagon with HVX
Key Takeaway from Examples
• To program even a simple imaging filter in intrinsics and assembly requires a large degree of
expertise in:
• HVX architecture: knowledge of HVX instruction set, optimal packetization of instructions
• HVX microarchitecture: latency of instructions, why stalls are caused, latency of prefetch,
cache, etc
• Expertise in image algorithms
• Halide’s goal is to significantly reduce the expertise needed in HVX architecture and
microarchitecture
• Halide allows programmer to focus development effort on image algorithms, thereby improving
programmer productivity

Write algorithm once, test and freeze algorithm after tests pass.
Then, alter schedules to explore optimizations to improve performance.
Never change algorithm again!
32
Advantages of using Halide vs Intrinsics or Assembly
 Development time and cost
 Significantly more time needed to author assembly/intrinsics compared to a Halide program
 Expertise
 Assembly/intrinsics require nuanced understanding of processor architecture and micro-architecture
 Only scales to a few programmers
 Halide allows a significantly larger set of developers to use HVX
 Halide allows programmers to focus on the algorithm and not on processor details
 Scalability
 Assembly and intrinsics programming does not scale to very large code bases
 Automatic optimization
 Halide allows optimizations across kernels for the entire image pipeline
 Not possible to optimize across libraries of assembly/intrinsics
 Halide allows programmers to easily tune program for performance
 Portability
 With Halide, no change in code required for new versions of Hexagon
 Compiler will automatically take advantage of new hardware features and instruction set

33
Halide HVX v60 Performance on Hexagon Simulator
Halide Performance vs. Hand-optimized Intrinsic Benchmarks
Higher is Better, 100% equals intrinsic performance
1.4 Testing on Simulator with Perfect Cache Behaviour
125.94%
1.2
109.06%
104.51%
100.40% 101.12%
1 95.90% 95.16% 95.88%
86.71%
0.8

0.6

0.4

0.2

34
Thank you
Follow us on:
For more information, visit us at:
www.qualcomm.com & www.qualcomm.com/blog

Nothing in these materials is an offer to sell any of the components or devices referenced herein.
©2017 Qualcomm Technologies, Inc. and/or its affiliated companies. All Rights Reserved.
Qualcomm is a trademark of Qualcomm Incorporated, registered in the United States and other countries. Other products and brand names
may be trademarks or registered trademarks of their respective owners.
References in this presentation to “Qualcomm” may mean Qualcomm Incorporated, Qualcomm Technologies, Inc., and/or other subsidiaries
or business units within the Qualcomm corporate structure, as applicable. Qualcomm Incorporated includes Qualcomm’s licensing business,
QTL, and the vast majority of its patent portfolio. Qualcomm Technologies, Inc., a wholly-owned subsidiary of Qualcomm Incorporated,
operates, along with its subsidiaries, substantially all of Qualcomm’s engineering, research and development functions, and substantially all
of its product and services businesses, including its semiconductor business, QCT.

You might also like