Disclaimer

The content of this blog is my personal opinion only. Although I am an employee - currently of Nvidia, in the past of other companies such as Iagination Technologies, MIPS, Intellectual Ventures, Intel, AMD, Motorola, and Gould - I reveal this only so that the reader may account for any possible bias I may have towards my employer's products. The statements I make here in no way represent my employer's position, nor am I authorized to speak on behalf of my employer. In fact, this posting may not even represent my personal opinion, since occasionally I play devil's advocate.

See http://docs.google.com/View?id=dcxddbtr_23cg5thdfj for photo credits.

Friday, October 08, 2010

MS License Lock Box - yeah, right

Last year I gave in and purchased a copy of Microsoft Office. "Gave in" because I mainly use Open Office. Gave in, because (a) there was a cheap deal on Office 2007 Home and Student - 80$ for license to install on three machines, (b) I had just realized that my Vista tablet had functional speech recognition, no need to buy expensive Dragon, and my hands were in spasm (much as I prefer open source, I am not aware of any free software that does good speech recognition, or handwriting for that matter), and (c) I have grown to depend on Microsoft OneNote. (This last really minor, just a nice to have.)

80$ to install on three machines. Sounds good, eh?

Also, at the same time I purchased the optional "License Lock Box", which supposedly gave me the right to re-download the software for 3 years.

I installed the software immediately on my tablet. Did not get around to installing it on my wife & daughter's compute(s) for a few months. Was annoyed when I tried to that the original download rights lasted 60 days. I thought the License Lock Box was supposed to give me more time than that, but could not figure it out.

Wrote it off as yet more money poured down the drain into Microsoft.

Today, decided to try to set my daughter up. Her mother and I are Luddites: my daughter can't tupe. But here new school requires assignments on computer. Typing lessons are icumin in, but in the meantime, speech recognition. Which works better on Vista, using Microsoft Office.

Since I had long given up hope of using my Office 2007 license, I started purchasing Office 2010. Filled out all the forms, pressed the button "after which your credit card will be charged" - and was taken to a page that said "No such page found". On Microsoft's store website, using Microsoft Internet Explorer.

Sigh. Called Microsoft Store help. It appears that my transaction did not go through. But while I was on the line, asked about my Office 2007 license, and the "Licensing Lock Box".

The very helpful guy on the phone explained that, at that time, software sold from Microsoft's website was sold through a reseller, Digital River. And that the License Lock Box was their product, not Microsoft's. Aha!

Found that I could log in - with one of the umpteen Microsoft LiveId accounts.

Curiously, with Chrome and Firefox I can see my purchase history. But I can't see the "Download Now" button that I am supposed to use the re-download.

But with Internet Explore, I get told they have no history of my purchase. Again, it is curious that such a Microsoft-related site works worse with Internet Explorer than with non-MS browsers. But then again, it doesn't work welll with either.

So, annoyingly, it looks as if I *MIGHT* be able to exercise my license rights to 3 installs of Offoce 2007. But because of website brokenness, not before Monday. And Sophie has homework to do this weekend.

God! This is one of the big advantages of Open Source: if you have a problem, you can just re-download at any time. On any computer. No licensing hoops to jump through using information that can only be finagled out of the software reseller''s broken website on weekdays.

---

I thought that buying this "License Lock Box" was a Microsoft approximation to always being able to download the latest software from the cloud. Maybe so - but it's a bad approximation. Apparently not even from Microsoft.

Although the helpful guy at the Microsoft store said that they allow infinite re-downloads.

Thursday, October 07, 2010

Accumulator ISA vs Uarch

wiki at: http://semipublic.comp-arch.net/wiki/Accumulator_ISA_vs_Uarch

oldder article on accumulators:
http://semipublic.comp-arch.net/wiki/Accumulators

I'm at home sick today, so I've got to be careful: last time I posted on comp.arch when I was home sick, I set the agenda for 4+ years of work.

First: 22+ gates may well fit in a pipestage. People are headed past 28 FO4, in an effort to tolerate device variation (the more gates / pipestage, the higher your yield).

Of course, usually when you do this we end up trying to cram several pipestages worth of work into one. As you might say redundant bypassing does.

---

As for accumulator architectures and microarchitectures, love/hate.

First, we must distinguish instruction set architecture from microarchitecture.

= Accumulator ISA =

Accumulator ISAs save bits. May lead to very small code. When we have the ability to reorganize instructions over long distances, accumulator ISAs don't need to hurt performance.

By the way, some might say that "2 operand" ISAs are accumulator based:

rD += rS

Myself, although more accumulator like that three operand (I hate these terms, but must use them)

rD := rS1 + rS2

I tend to be a stickler, and say that either there is single accumulator

acc += rS

or maybe a small number of accumulators, acc0 - 3 versus r0-32

acc0-3 += rS0-31

== Accumulator versus Stack ==

By the way, for similar instruction size issues, I sometimes look fondly on stack ISAs. Even fewer bits than accumulators.

= Accumulator Microarchitecture =

Now, let's transition into microarchitecture. I call it an accumulator microarchitecture when the accumulator (or acccumulators) are "close to" one or more ALUs.

I.e. you may have a small number, say 4, of accumulators near to every individual ALU. E.g. you might have 3 ALUs, with 4 accumulators each.

Or you may have a small number of accumulators shared between a group of ALUs.

Physically, the term accumulator may be associated with a different circuit design: e.g. the accumulators might be flops, whereas the registers might be in an SRAM array.

I don't call it an accumulator microarchitecture when you have, say, 2 clusters of 4 ALUs, each tightly bound to 16 registers. I call that a partitioned register file. But I might be willing to call it an accumulator if there were only 4 such tightly bound registers next to the ALUs. Obviously, this is a matter of degree.

I might call it an accumulator architecture if there were 2 such ALU clusters, each with 4 accumulator registers, and a big shared pool of 64 registers eqaually accessible to all. But I would require that there
be instructions of the form

cluster.accum_i += global_reg_j

If the global registers could not be used as operands of at least the usual ADD instruction, but were restricted to moving to and from the accumulators, I would call it a two level register file, not an accumulator microarchitecture.

== OOO implementation of Accumulator ISA ==

Accumulator ISAs implemented on accumulator microarchitectures are natiral for in-order machines.

On an out-of-order machine, it is trivial to rename the accumulators of the ISA to a single PRF. In which case, the hypothetical advantages of the accumulator ISA are lost.

== OOO implementation of Accumulator Microarchitecture ==

Conversely, it is straightforward to implement a "bypass cache" for a flat register file instruction set, taking advantage of the fact that a value need not be written into the main register file before it is reused. A bypass cache is a generalization of generic bypassing: a bypass cache adds state, and is not just restricted to bypassing from operands in flight.

The bypass cache state is very much like an accumulator microarchitecture. With at least one important difference:

If the bypass cache is CAM indexed by the physical register number in the main RF, then that is an important difference. A second important difference is whether the bypass cache can miss - whether a value you expect to receive from the bypasses or the bypass cache may not be there when you expect it to be, so that you have to fetch it froom the main RF. I sometimes call this a priori vs a posteriori caching.

If, however, there is separate renaming for accumulator registers and main registers, then you more exactly have an OOO implementation of, say, a flat RF ISA on an accumulator uarch. But you have all sorts of questions about policy: when do you make a copy of a main RF register in an accumulator, and vice versa.

(Hey, here's an idea: in the scheduler, CAM on main REF regnums. But also broadcast when a main RF regnum has been moved to an accumulator. Issue the instruction with non-CAM indexed accum regnums... How handlle replacemeent? Probably LRU, modified by overiting - so many values are only read once.)

== OOO implementattion of Accumulator ISA on Accumulator Uarch ==

What about combining the two? Well, obviously, you could rename from ISA accum into flat RF, and then into uarch accums. But that rather defeats the purpose.

We might rename accums and main regs separately. The ISA accums guide replacement in the physical accums.

Issue: what if ISA accums and physical accums are not the same in number?

Here's an observation: one of the biggest advantages of accumulator ISAs is that they tend to reuse the accumulators quickly. I.e. they tell us when values are dead, and hence can be more quickly recycled. You might get the same effect by a "kill register" bit.

= Summary =

Accumulators, whether ISA or uarch, are part of our tool kit.

I do not thing that there is a uniform way of saying one is better than another. Certainly, at the moment flat RFs preponderate.

Much of the benefit of accumulators can be obtained by bypass caching.

I would hesitate to add true accumulators to a new ISA unless (a) codesize really matters, or (b) it is an embedded system, with the ability to change uarch and ISA every generation.

(But then, that's what they always say.)

On the other hand, I am scared of implementing accumulators, whether in ISA or uarch.

== Accumulators for Extended Precision ==

I forgot to mention one of the biggest advantages of accumulators: extended intermediate precision.

Many DSPs have, for example, 24 bit accumulators to add chains of 16 bit numbers.

One might consider FMA or FMAC, floating point multipply add without intermediate rounding, to be a hidden internal accumulator. Except that it isn't - it flows. If you exposed that intermediate value...

I keep waiting for a nice formulation of exact, infinte precision, vector sum reductions, dot products, etc. Trivially, that can be done via a [[superaccumulator]] - but although I like superaccumulators, they are pretty expensive. What, 1K or 2K bits?

An ISA-level accumulator architecture of the form

superacc := 0
for all i superacc += a[i]

is nice in that you could imagine mapping it to the infinite internal precision versions of 4-way dot product, etc., that one sees in some instruction sets. (E.g. Microunity)

I'd like to see lower cost but still infinite precision wayys ofdoing such FP vector reductions.

Tuesday, September 21, 2010

Vector_Lanes_versus_Packed_Operations

= Packed =

For want of a better term, I will use the phrase [[Packed Operations]] to refer to instruction set extensions such as Intel MMX, SSE, PowerPC Altivec, etc.:
typically operating on 64 or 128 bit data (although people did propose [[32 bit MMX]], and 256 bit AVX is coming soon in 2010).

Typically operating on
* 8x8b or 16x8b
* 4x16b or 8x16b
* 2x32b or 4x32b
etc.

Typically operating SIMD-style inside ALU operations,
but typically lacking scatter/gather memory operations.

= Packed vs Vector Lanes =

I want to contrast this with microarchitectures that have parallel vector lanes.
(NOT [[vector sequential]] microarchitectures.)

Packed Operations are fundamentally scalar pipelines. They just happen to have wide scalar datapaths, e.g. 64bits.
Since there are typically no 128 bit scalar datapaths, they have evolved beyond scalar;
but typically the datapath is designed as if it is a wide ALU datapath.

Parallel vector lane microarchitectures, on the other hand, are typically formed ourt of multiple indeoendent ALUs.

Packed ALUs are typically a single ALU, that is subdivided to perform independent packed operations.
E.g. one might take a 64-bit wide adder, and add special buffer bits at every byte boundary.
But controlling the values of these buffer bits, we can control whether carry will propagate across 8b, 16b, or 32b boundaries.
I.e. a 64 bit wide ALU with such byte boundary buffer bits
is really a 72 bit wide ALU,
capable of performing 8x8b, 4x16b, and 2x32b, as well as 64 bit addition.
(For that matter, odd sizes such as 24bit arithmetic can also be achieved.)

Similarly for 128 bit packed datapaths. Although nobody probably wants to build a 128 bit wide carry propagate adder.

Whereas in a vector lane microarchitecture, the ALUs are independent.
E.g, in 512 bit wide vector machine with 16 32b lanes,
there are 16 32b wide adders.
In such a machine crossing vector lanes is difficult.

Of course there is a spectrum of possibilities.
For example, pairs of even and odd vector lanes may be combined to perform double precision arithmetic.
Or, one may have vector lanes, where the operations within the lanes are 128b packed operations.

(128b packed is particularly pleasant as a lane width, since it supports the common 4x32b vectors, as well as 2x64b complex.)

Even on a packed datapath, certain operations that move data between bits are difficult.
E.g. shifts require special handling of buffer bits.
It is more difficult to partition a 64x64bit integer multiplier into 32b*32b multipliers,
than it is to simply add buffer bits for add - nevertheless, it can be done.

(Note that a 64b*64b integer multiplier can be partitioned into 4 32b*32b multipliers - roughly what is required for complex multiplication or an FFT 2-butterfly.)

Floating point is even more difficult to partition. The multiplier array for an FMA can be shared between 32b and 64b.
The adder logic is more challenging.

Neverthelerss: considerable sharing is possiblwe on a packed datapath.
But at some point one graduates to separate ALUs for vector lanes.

In "separate ALUs", the operative term is "separated". Physically separated ALUs are part of a vector lane microarchitecture.

= Instruction Set Design Consequences =

In a packed architecture, one tends to have N-bits, subdivided into more or viewer smaller pieces.

In vector architectures, one tends to have vector elements of a given width, say VL * EW, where EW is the element width.

One might then have narrower operations that apply to vector elements,
e.g. a vector of VL 32b floats or a vector of VL 64b floats.

(Although one might have packed operations on the lane width vector elements.)

There may be operations that load a vector of 8, 16, or 32 bit elements,
packed in memory, into unpacked 64 bit elements within a vector register.
Whereas on a packed instruction set, one probably just loads the values without unpacking them.

Consider, e.g. 16b wide floating point.
Many machines expand it into 32b floating point in registers.
But one can imagine ALUs that operate on 16b FP in registers.

I.e. packed operations are about using all of the bits of the register datapath.
Whereas vector lane operations are about vector operations on a limited number of datatypes.

Wifi disppears from HP TX 1420 tablet PC

My wife and daughter's HP TX 1420 Tablet PC (originally my wife's, then my daughter's) suddenly behaves as if it no longer has wifi builtin.

"Suddenly" may not be true - it has probably been attached to wired ethernet for a few months. I don't know when wifi disappeared. But it has gone now.

As the link shows, this is apparently a well known problem with HP machines.

Tuesday, September 07, 2010

Varieties of Cache - CompArch

Varieties of Cache - CompArch: "Varieties of Cache"

The basic principle of caching is to use a small, fast structure (typically an [[Array]])
improve the performance of a large slow, structure,
hopefully to approximate a large, fast, structure, without the expense.

However, the definition of "fast" may vary. And there may be other reasons to use a cache.

The most familiar caches are [[latency caches]].
E.g. an L1 data cache that may take 4 cycles to access, an L2 20 cycles, and main memory 200 cyckes.

Another useful cache is a [[bandwidth cache]], where the cache provides more bandwidth than the structure is is a cache for.
This is quite common - often latency and bandwidth caches are combined.
However, the use of caches to improve bandwidth sometimes leaves customers dispirited,
such as those on the [[High bandwidth Computing]] mailing list.

Another useful cache has many array read and write ports on the small cache, and fewer on the large structure. E.g. [[array port reduction]].
This is really a particular form of [[bandwidth cache]].

A cache is a fairly good [[read combining]] or [[write combining]] mechanism.

A [[power cache]] attempts to reduce power by keeping frequently accessed data items in the small structure.
this may be done even without an improvement in latency or bandwidth.

Finally(?), a reliability cache may keep certain items expected to have relaibility issues in the cache.
Particularly if reliability is related to frequency of access.

TBD: are there any other varieties of cache?

Array Port Reduction - CompArch

Array Port Reduction - CompArch: "Array Port Reduction"


AFAIK "RF Port Reduction" was invented by Dave Papworth on the Intel P6 circa 1991. At that time called "ROB Read Port Reduction". Based on observation that most uops' inputs were captured by the RS, while the ROB read ports were actually

See
* [[Register File Port Reduction]]
* [[Register Renamer Port Reduction]]

After the above, I note some generic trends:

Say that you have N operations, each with L inputs and K outputs. How do you avoid having to access
the array containing such inputs and outputs with N*L read ports and N*K write ports?

I observe that these techniques apply, not just to the RF and RR arrays mentioned above, bit also to other arrays:
* Generic Cache Arrays
** e.g. banking as a form of [[pseudo dual porting]]
* RF arrays
* [[Store Buffers]]
* [[Branch Predictor Arrays]], in particular [[BTB Arrays]]
* Nearly any large [[Queue or Buffer]], such as those in store and forward networks such as the memory hierarchy.
** See [[The Memory Hierarchy is a Store and Forward Network]]

Similar principles of array port reduction apply to all of these arrays.
Simplest is when the arrays are indexed solely and uniquely, e.g. by a memory address or register number.
One might say that these are the primary key.
More challenging is when the array has such a *spatial* index key,
but also has a *temporal* aspect.
E.g. "find the youngest store to the same address older than the present store".

Spatial/temporal may well be a useful distinction, although two dimensional X/Y may also apply.

= Bypassing =

The first principle is as mentioned in the examples of RF port reduction and renamer port reduction:
that group of N operations may not really need to do N*L reads and N*K writes.
Since we are often talking about instructions, some instructions may produce values that later instructions consume. I call this generically "bypassing": it may take the form of conventional execution unit bypassing, or dependency checks inside a block of instructions at the renamer. The P6 [[Capture RS]] that led to Papworth's original ROB Read Port Reduction is a form of [[bypass cache]] in some sense.

= Banking =

Classic spatial banking: banks in a pseudo-multiported cache. Banks in a large register file, such as a GPU.

Banking often seeks to do the opposite of [[spatial locality]] - you try to arrange the banking function, usually a bitfield extraction, occasionally a hash - so that locations likely to occur together are likely to occur in different banks, not the same.


Temporal banking - or otherwise exploiting temporal proximity. E.g. as described in [[Register Renamer Port Reduction]], where uops' inputs are compared to neighbouring older uops first, and then to more distant uops only if the recent predecessor comparison fails.

If these comparisons are done in batches with hard boundaries, it is a form of temporal banking.
If these comparisons are done smoothly - all neighbous compared, etc. - then it is a different way of exploiting temporal proximity, not banking.
Intermediate between these is to divide the temporally sorted array into banks,
and to always compare an element to two or three banks:
* 3 banks: the bank the element is in, the preceding and succeeding bank.
* 2 banks:
** the bank the unit is in
** the preceding bank if the element is close to the beginning of the bank
** the succeeding bank if the element is close to the end of the bank
** possibly no other bank, if the element is in the middle of its own bank.


    E.g. based on the two most significant bits of the sequence number
    00bb...b => compare to this bank plus preceding
    11bb...b => compare to this bank plus succeeding
    01bb...b OR 10bb...b => don't compare
    or 3 bits ...

    [[AG Novelty?]] - I've never seen this proposed before. It seems so obvious...




= Read and Write Combining =

TBD: combining circuits:

;(1) CAMs: compare all operations to all operations

;(2) Choose N oldest (or highest priority) unique. Then CAM for combining.

;(3) Spatial hash to queues.
Within the queues
* CAM
* or just compare nearest neighbours

;(4) Sorting networking

;Sort by index.
Choose N lowest.
ISSUE: loss of age or priority info

;Sort by index, spatially
;Also sort by priority, e.g. time.
(Maybe different sorts, time and priority)

Spatial sort is of tuples (index,seqnum).
When matching indexes (index,seqnum1), (index,seqnum2) link seqnum2 to seqnum1,
and only keep (index,seqnum1) in the sorting datastructure.

Equivalent, keep redundant values in the temporal sort.

Compute dominators in the temporal sort. Extract the N highest priority dominatos in the temporal sort.

Sounds expensive. Less expensive time-wise if thinking about special sorting hardware.

Bluesky.

= Caches =

Small highly ported array,
combined with a larger, less ported array.

May exploit temporal and/or spatial locality.

E.g. may have 1r/1w port on an array of large cache line of 64 bytes,
but have more, narrower, ports within a smaller array.

May use such a cache not to improve latency, but solely to manage ports.
Which are a special form of bandwidth cache. (See [[Varieties of Cache]].)

= TBD =

Q: what other forms of array port reduction have I encountered?