transactional memory
DESCRIPTION
Transactional Memory. Jaehyuk Huh Computer Science, KAIST Based on Lectures by Prof. Arun Raman, Princeton University. Parallel Programming. Find independent tasks in the algorithm Map tasks to execution units (e.g. threads) Define and implement synchronization among tasks - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/1.jpg)
CS492B Analysis of Concurrent Programs
Transactional Memory
Jaehyuk HuhComputer Science, KAIST
Based on Lectures by Prof. Arun Raman, Princeton University
![Page 2: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/2.jpg)
2
Parallel Programming
1. Find independent tasks in the algorithm2. Map tasks to execution units (e.g. threads)3. Define and implement synchronization among tasks
1. Avoid races and deadlocks, address memory model issues, …
4. Compose parallel tasks5. Recover from errors6. Ensure scalability7. Manage locality8. …
![Page 3: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/3.jpg)
3
Parallel Programming
1. Find independent tasks in the algorithm2. Map tasks to execution units (e.g. threads)3. Define and implement synchronization among tasks
1. Avoid races and deadlocks, address memory model issues, …
4. Compose parallel tasks5. Recover from errors6. Ensure scalability7. Manage locality8. …
Transactional Memory
![Page 4: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/4.jpg)
4
Transactional Programming
void deposit(account, amount) { lock(account); int t = bank.get(account); t = t + amount; bank.put(account, t); unlock(account);}
void deposit(account, amount) { atomic { int t = bank.get(account); t = t + amount; bank.put(account, t); }}
1. Declarative Synchronization – What, not How2. System implements Synchronization transparently
![Page 5: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/5.jpg)
5
Transactional Memory
Memory Transaction - An atomic and isolated sequence of memory accesses
Transactional Memory – Provides transactions for threads running in a shared address space
![Page 6: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/6.jpg)
6
Transactional Memory - Atomicity
Atomicity – On transaction commit, all memory updates appear to take effect at once; on transaction abort, none of the memory updates appear to take effect
void deposit(account, amount) { atomic { int t = bank.get(account); t = t + amount; bank.put(account, t); }}
Thread 1 Thread 2
RD A : 0RD
WRRD A : 0
WR A : 10
WR A : 5COMMIT
ABORT
CONFLICT
![Page 7: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/7.jpg)
7
Transactional Memory - Isolation
Isolation – No other code can observe updates before commit
Programmer only needs to identify operation sequence that should appear to execute atomically to other, concurrent threads
![Page 8: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/8.jpg)
8
Transactional Memory - Serializability
Serializability – Result of executing concurrent transactions on a data structure must be identical to a result in which these transactions executed serially.
![Page 9: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/9.jpg)
9
Some advantages of TM
1. Ease of use (declarative)2. Composability3. Expected performance of fine-grained locking
![Page 10: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/10.jpg)
10
Composability : Locks
void transfer(A, B, amount) { synchronized(A) { synchronized(B) { withdraw(A, amount); deposit(B, amount); } }}
void transfer(B, A, amount) { synchronized(B) { synchronized(A) { withdraw(B, amount); deposit(A, amount); } }}
1. Fine grained locking Can lead to deadlock2. Need some global locking discipline now
![Page 11: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/11.jpg)
11
Composability : Locks
void transfer(A, B, amount) { synchronized(bank) { withdraw(A, amount); deposit(B, amount); }}
void transfer(B, A, amount) { synchronized(bank) { withdraw(B, amount); deposit(A, amount); }}
1. Fine grained locking Can lead to deadlock2. Coarse grained locking No concurrency
![Page 12: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/12.jpg)
12
Composability : Transactions
void transfer(A, B, amount) { atomic { withdraw(A, amount); deposit(B, amount); }}
void transfer(B, A, amount) { atomic { withdraw(B, amount); deposit(A, amount); }}
1. Serialization for transfer(A,B,100) and transfer(B,A,100)2. Concurrency for transfer(A,B,100) and transfer(C,D,100)
![Page 13: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/13.jpg)
13
Some issues with TM
1. I/O and unrecoverable actions2. Atomicity violations are still possible3. Interaction with non-transactional code
![Page 14: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/14.jpg)
14
Atomicity Violation
atomic { … ptr = A; …}
atomic { … ptr = NULL;}
Thread 2Thread 1
atomic { B = ptr->field;}
![Page 15: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/15.jpg)
15
Interaction with non-transactional code
lock_acquire(lock); obj.x = 1; if (obj.x != 1) fireMissiles();lock_release(lock);
obj.x = 2;
Thread 2Thread 1
![Page 16: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/16.jpg)
16
Interaction with non-transactional code
atomic { obj.x = 1; if (obj.x != 1) fireMissiles();}
obj.x = 2;
Thread 2Thread 1
![Page 17: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/17.jpg)
17
Interaction with non-transactional code
atomic { obj.x = 1; if (obj.x != 1) fireMissiles();}
obj.x = 2;
Thread 2Thread 1
Weak Isolation – Transactions are serializable only against other transactionsStrong Isolation – Transactions are serializable against all memory accesses (Non-transactional LD/ST are 1-in-struction TXs)
![Page 18: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/18.jpg)
18
Nested Transactions
void transfer(A, B, amount) { atomic { withdraw(A, amount); deposit(B, amount); }}
void deposit(account, amount) { atomic { int t = bank.get(account); t = t + amount; bank.put(account, t); }}
Semantics of Nested Transactions• Flattened• Closed Nested • Open Nested
![Page 19: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/19.jpg)
19
Nested Transactions - Flattened
int x = 1;atomic { x = 2; atomic flatten { x = 3; abort; }}
![Page 20: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/20.jpg)
20
Nested Transactions - Closed
int x = 1;atomic { x = 2; atomic closed { x = 3; abort; }}
![Page 21: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/21.jpg)
21
Nested Transactions - Open
int x = 1;atomic { x = 2; atomic open { x = 3; } abort;}
![Page 22: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/22.jpg)
22
Nested Transactions – Open – Use Case
int counter = 1;atomic { … atomic open { counter++; }}
![Page 23: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/23.jpg)
23
Transactional Programming - Summary
1. Transactions do not generate parallelism2. Transactions target performance of fine-grained locking @ effort of coarse-grained locking3. Various constructs studied previously (atomic, retry, orelse,…) 4. Different semantics (Weak/Strong Isolation, Nesting)
![Page 24: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/24.jpg)
24
TM Implementation
Data Versioning• Eager Versioning• Lazy Versioning
Conflict Detection and Resolution• Pessimistic Concurrency Control• Optimistic Concurrency Control
Conflict Detection Granularity• Object Granularity• Word Granularity• Cache line Granularity
![Page 25: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/25.jpg)
25
Data Versioning
Eager Versioning (Direct Update) Lazy Versioning (Deferred Update)
![Page 26: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/26.jpg)
26
Conflict Detection and Resolution - PessimisticTi
me
No Conflict Conflict with Stall Conflict with Abort
![Page 27: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/27.jpg)
27
Conflict Detection and Resolution - OptimisticTi
me
No Conflict Conflict with Abort Conflict with Commit
![Page 28: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/28.jpg)
28
TM Implementation
Data Versioning• Eager Versioning• Lazy Versioning
Conflict Detection and Resolution• Pessimistic Concurrency Control• Optimistic Concurrency Control
Conflict Detection Granularity• Object Granularity• Word Granularity• Cache line Granularity
![Page 29: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/29.jpg)
29
Examples
Hardware TM • Stanford TCC: Lazy + Optimistic• Intel VTM: Lazy + Pessimistic• Wisconsin LogTM: Eager + Pessimistic• UHTM• SpHT
Software TM • Sun TL2: Lazy + Optimistic (R/W)• Intel STM: Eager + Optimistic (R)/Pessimistic (W)• MS OSTM: Lazy + Optimistic (R)/Pessimistic (W)• Draco STM• STMLite• DSTM
Can find many more at http://www.dolcera.com/wiki/index.php?title=Transactional_memory
![Page 30: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/30.jpg)
30
Software Transactional Memory (STM)
atomic { a.x = t1 a.y = t2 if (a.z == 0) { a.x = 0 a.z = t3 }}
tmTXBegin()tmWr(&a.x, t1)tmWr(&a.y, t2)if (tmRd(&a.z) != 0) { tmWr(&a.x, 0) tmWr(&a.z, t3)}tmTXCommit()
![Page 31: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/31.jpg)
31
Intel McRT-STM
Strong or Weak Isolation WeakTransaction Granularity Word or ObjectLazy or Eager Versioning EagerConcurrency Control Optimistic read, Pessimistic
Write
Nested Transaction Closed
![Page 32: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/32.jpg)
32
McRT-STM Runtime Data Structures
Transaction Descriptor (per thread)• Used for conflict detection, commit, abort, …• Includes read set, write set, undo log or write buffer
Transaction Record (per datum)• Pointer-sized record guarding shared datum• Tracks transactional state of datum
Shared: Read-only access by multiple readersValue is odd (low bit is 1)
Exclusive: Write-only access by single ownerValue is aligned pointer to owning transaction’s descriptor
![Page 33: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/33.jpg)
33
atomic { t = foo.x; bar.x = t; t = foo.y; bar.y = t; }
T1
atomic { t1 = bar.x; t2 = bar.y; }
T2
• T1 copies foo into bar• T2 reads bar, but should not see intermediate values
Class Foo { int x; int y;};Foo bar, foo;
McRT-STM: Example
![Page 34: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/34.jpg)
34
stmStart(); t = stmRd(foo.x); stmWr(bar.x,t); t = stmRd(foo.y); stmWr(bar.y,t); stmCommit();
T1
stmStart(); t1 = stmRd(bar.x); t2 = stmRd(bar.y); stmCommit();
T2
• T1 copies foo into bar• T2 reads bar, but should not see intermediate values
McRT-STM: Example
![Page 35: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/35.jpg)
35
McRT-STM OperationsSTM read (Optimistic)• Direct read of memory location (eager versioning)• Validate read data• Check if unlocked and data version <= local timestamp• If not, validate all data in read set for consistency
validate() {for <txnrec,ver> in transaction’s read set, if (*txnrec != ver) abort();}• Insert in read set• Return valueSTM write (Pessimistic)• Validate data• Check if unlocked and data version <= local timestamp
• Acquire lock• Insert in write set• Create undo log entry• Write data in place (eager versioning)
![Page 36: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/36.jpg)
36
stmStart(); t = stmRd(foo.x); stmWr(bar.x,t); t = stmRd(foo.y); stmWr(bar.y,t); stmCommit;
T1stmStart(); t1 = stmRd(bar.x); t2 = stmRd(bar.y); stmCommit();
T2
hdrx = 0y = 0
5hdrx = 9y = 7
3foo bar
Reads <foo, 3> Reads <bar, 5>
T1
x = 9
<foo, 3>Writes <bar, 5>Undo <bar.x, 0>
T2 waits
y = 7
<bar.y, 0>
7
<bar, 7>
Abort
•T2 should read [0, 0] or should read [9,7]
Commit
McRT-STM: Example
![Page 37: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/37.jpg)
Hardware Transactional Memory• Transactional memory implementations require tracking
read / write sets• Need to know whether other cores have accessed data we
are using• Expensive in software
– Have to maintain logs / version ID in memory– Every read / write turns into several instructions– These instructions are inherently concurrent with the actual accesses, but
STM does them in series
![Page 38: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/38.jpg)
Hardware Transactional Memory• Idea: Track read / write sets in Hardware
– Unlike Hardware Accelerated TM, handle commit / rollback in hardware as well
• Cache coherent hardware already manages much of this• Basic idea: map storage to cache• HTM is basically a smarter cache
– Plus potentially some other storage buffers etc
• Can support many different TM paradigms– Eager, lazy– optimistic, pessimistic
• Default seems to be Lazy, pessimistic
![Page 39: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/39.jpg)
HTM – The good• Most hardware already exists• Only small modification to cache needed
Core
RegularAccesses
L1 $
Tag
Dat
a
L1 $
Kumar et al. (Intel)
![Page 40: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/40.jpg)
HTM – The good• Most hardware already exists• Only small modification to cache needed
Core
RegularAccesses
Transactional $L1 $
Tag
Dat
a
Tag
Add
l. Ta
g
Old
Dat
a
New
Dat
a
Transactional Accesses
L1 $
Kumar et al. (Intel)
![Page 41: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/41.jpg)
HTM Example
Tag data Trans? State Tag data Trans? state
atomic { read A write B =1}
atomic { read B
Write A = 2 }
Bus Messages:
![Page 42: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/42.jpg)
HTM Example
Tag data Trans? State Tag data Trans? state
B 0 Y S
atomic { read A write B =1}
atomic { read B
Write A = 2 }
Bus Messages: 2 read B
![Page 43: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/43.jpg)
HTM Example
Tag data Trans? State Tag data Trans? stateA 0 Y S
B 0 Y S
atomic { read A write B =1}
atomic { read B
Write A = 2 }
Bus Messages: 1 read A
![Page 44: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/44.jpg)
HTM Example
Tag data Trans? State Tag data Trans? stateA 0 Y S
B 1 Y M B 0 Y S
atomic { read A write B =1}
atomic { read B
Write A = 2 }
Bus Messages: NONE
![Page 45: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/45.jpg)
Conflict, visibility on commit
Tag data Trans? State Tag data Trans? stateA 0 N S
B 1 N M B 0 Y S
atomic { read A write B =1}
atomic { read B
ABORT
Write A = 2 }
Bus Messages: 1 B modified
![Page 46: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/46.jpg)
Conflict, notify on write
Tag data Trans? State Tag data Trans? stateA 0 Y S
B 1 Y M B 0 Y S
atomic { read A write B =1 ABORT?}
atomic { read B
ABORT?
Write A = 2 }
Bus Messages: 1 speculative write to B 2: 1 conflicts with me
![Page 47: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/47.jpg)
HTM – The good Strong isolation
![Page 48: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/48.jpg)
HTM – The good ISA Extensions
• Allows ISA extentions (new atomic operations)• Double compare and swap• Necessary for some non-blocking algorithms
• Similar performance to handtuned java.util.concurrent implementation (Dice et al, ASPLOS ’09)
int DCAS(int *addr1, int *addr2, int old1, int old2, int new1, int new2)atomic {
if ((*addr1 == old1) && (*addr2 == old2)) { *addr1 = new1; *addr2 = new2; return(TRUE);
} else return(FALSE); }
![Page 49: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/49.jpg)
HTM – The good ISA Extensions
• Allows ISA extentions (new atomic operations)• Atomic pointer swap
Elem 1
Elem 2
Loc 1
Loc 2
![Page 50: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/50.jpg)
HTM – The good ISA Extensions
• Allows ISA extentions (new atomic operations)• Atomic pointer swap
– 21-25% speedup on canneal benchmark (Dice et al, SPAA’10)Elem 1
Elem 2
Loc 1
Loc 2
![Page 51: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/51.jpg)
HTM – The bad False Sharing
Tag data Trans? State Tag data Trans? stateC/D 0/0 Y S
atomic { read A write D = 1}
atomic { read C
Write B = 2 }
Bus Messages: Read C/D
![Page 52: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/52.jpg)
HTM – The bad False Sharing
Tag data Trans? State Tag data Trans? stateC/D 0/0 Y S
A/B 0/0 Y S
atomic { read A write D = 1}
atomic { read C
Write B = 2 }
Bus Messages: Read A/B
![Page 53: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/53.jpg)
HTM – The bad False sharing
Tag data Trans? State Tag data Trans? stateC/D 0/1 Y M C/D 0/0 Y S
A/B 0/0 Y S
atomic { read A write D = 1}
atomic { read C
Write B = 2 }
Bus Messages: Write C/D
UH OH
![Page 54: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/54.jpg)
HTM – The bad Context switching
• Cache is unaware of context switching, paging, etc• OS switching typically aborts transactions
![Page 55: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/55.jpg)
HTM – The bad Inflexible
• Poor support for advanced TM constructs• Nested Transactions• Open variables• etc
![Page 56: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/56.jpg)
HTM – The bad Limited Size
Tag data Trans? State Tag data Trans? stateA 0 Y M
atomic { read A read B read C read D} Write C/
Bus Messages: Read A
![Page 57: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/57.jpg)
HTM – The bad Limited Size
Tag data Trans? State Tag data Trans? stateA 0 Y M
B 0 Y M
atomic { read A read B read C read D}
Bus Messages: Read B
![Page 58: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/58.jpg)
HTM – The bad Limited Size
Tag data Trans? State Tag data Trans? stateA 0 Y M
B 0 Y M
C 0 Y M
atomic { read A read B read C read D}
Bus Messages: Read C
![Page 59: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/59.jpg)
HTM – The bad Limited Size
Tag data Trans? State Tag data Trans? stateA 0 Y M
B 0 Y M
C 0 Y M
atomic { read A read B read C read D}
Bus Messages: …
UH OH
![Page 60: Transactional Memory](https://reader036.vdocument.in/reader036/viewer/2022062520/5681639c550346895dd49833/html5/thumbnails/60.jpg)
Kumar (Intel)
Hardware vs. Software TM
Hardware Approach• Low overhead
– Buffers transactional state in Cache
• More concurrency– Cache-line granularity
• Bounded resource
Software Approach• High overhead
– Uses Object copying to keep transactional state
• Less Concurrency– Object granularity
• No resource limits
Useful BUT Limited Useful BUT Limited
What if we could have both worlds simultaneously?