Monday, March 16, 2020

Buds, Blooms, And Thorns Review Of Island Hopper By Eagle-Gryphon Games

Buds, Blooms, and Thorns Review of Island Hopper by Eagle-Gryphon Games
DisclaimerSupport me on Patreon!
Vitals:
Title: Island Hopper
Designed by: Scott Almes
Publisher: Eagle-Gryphon Games
Year Published: 2017
MSRP: $50
2-6p | 30-45 min | 8+

Introduction:
You and your friends all make a living by selling goods amongst a chain of beautiful tropical islands. Sounds great, right? Well, there's a problem. None of you are successful enough to buy your own seaplane, so you all pitched in and bought one together, which means that each day you all have to use the same plane to make all of the day's deliveries – and some of you aren't going to get paid. To make matters worse, the plane is in such disrepair that the instrumentation is broken, the compass demagnetized, and the windshield is covered in cracks, duct tape, and the remains of a few unfortunate seagulls, so the pilot might as well be flying blind...

Each day in Island Hopper, players auction off the Captain's seat; the player who becomes the Captain is in charge of flying the plane for the day, but cannot make any deliveries of their own. To make their deliveries, the other players bribe the Captain to fly to the islands to which they need to go, thereby earning themselves cash. When it's time for the Captain to fly, the Captain must close his eyes, pick up their goods tokens, and attempt to land them in an island's harbor. A successful landing means that players can fulfill their contracts and the captain collects his bribe — but if the goods splash into the sea, you might find yourself under water...

—description from the publisher

Blooms:
Blooms are the game's highlights and features.  Elements that are exceptional.
  • A silly combination of dexterity and social interaction with a fun bidding mechanic.
  • There are fun, strategic choices to make.
  • The artwork by Kwanchai Moriya is whimsical and the components are top notch.
  • There are lots of moments for laughs, as long as you don't take the game too seriously.
Buds:
Buds are interesting parts of the game I would like to explore more. 
  • This game isn't for everyone, but if you like social interaction and light strategy, give it a shot!
  • Having limited chances to say a single word has pros and cons.  On one hand, it prevents people from just shouting things out randomly, on the other hand, with certain players it results in no one saying anything.  It might be fun to try playing without the direction tokens and let the pilot have to figure out directions from a cacophony of different instructions.
Thorns:
Thorns are a game's shortcomings and any issues I feel are noteworthy.
  • The game is simple enough, but the rulebook could have used a few more runs by a proofreader.  There are a few typos and phrases that seem to be left over from the prototype (referring to coins as cubes, for example), the terms 'round' and 'phase' are used interchangeably, and there are a few details that seem to be missing (like what triggers the end game).
  • We found players hands tend to either rise from the table or drop closer to the table, so some players tend to drop the goods from higher up, resulting in more bounces and less successful landings, while others are almost placing the goods right onto the islands.  2-3 inches is an ideal height, but it's difficult for everyone to be consistent.
  • While the art throughout the game is pretty nice, the coins are super generic.  They're functional, but about as plain as could be.
  • There is a very high amount of luck in the game, particularly for what contracts and passengers are available to draw.
  • Missing from the rules is what the ruling should be (success or not) if a good is on an island and coins.  Not touching the table, but definitely supported by the coins surrounding the island.  We've been playing that the coins become an extension of the island (thus making it even more attractive to try to fly to), but there's no discussion of this in the rules at all.
Final Thoughts:
Island Hopper is the type of game that needs a very specific audience.  It's quite fun if people are willing to be goofy and silly, but it's not going to work well with people that are very analytical or strategic.  There is a bit of strategy, but it's overshadowed by some silly dexterity mechanics that can leave your best laid plans sunk in the water after a bad bounce.  If you go into the game understanding that the joy comes from the experience, regardless of if you win or lose, you'll have a good time.  This isn't a perfect game; there are some fiddly aspects to it, and for as casual as it is, there is a lot going on outside of the primary mechanics.  Whether you feel this enhances the game to move it up a notch from just a casual dexterity game, or just gets in the way of a silly dexterity filler is up to you and the group you play with.

This is a great game to play with the family, particularly the 8-15 age range.  I think the 12+ age limit is quite a bit higher than necessary - there are no complex mechanics or concepts.  Probably the limiting factor is how far across the table the players can reach since the islands can be spread out a bit.  I think if you like games like Colt Express, Junk Art, or similar light, silly games, Island Hopper might be a good choice for you!

Buds, Blooms, and Thorns Rating:
Bud!  This game definitely has some
great moments.  It's good for several plays
and should appeal to most gamers, especially
if you enjoy other games like this.
Pictures:


Follow Invedars and progress about the game on Facebook.

Tech Book Face Off: Programming Massively Parallel Processors Vs. Professional CUDA C Programming

After getting an introduction to GPU programming with CUDA by Example, I wanted to dig in deeper and get to know the real ins and outs of CUDA programming. That desire quickly lead to the selection of books for this Tech Book Face Off. The first book is definitely geared to be a college textbook, and as I spent years learning from books like this, I felt comfortable taking a look at Programming Massively Parallel Processors: A Hands-on Approach by David B. Kirk and Wen-mei W. Hwu. The second book is targeted more at the working professional, as the title suggests: Professional CUDA C Programming by John Cheng, Max Grossman, and Ty McKercher. I was surprised by both books, and not in the same way. Let's see how they do at teaching CUDA programming.

Programming Massively Parallel Multiprocessors front coverVS.Professional CUDA C Programming front cover

Programming Massively Parallel Processors

The polite way to critique this book is to say, it's somewhat verbose and repetitive, but if you can get past that, it has a lot to offer in the way of example CUDA programs that show how to optimize code for the GPU architecture. A slightly less polite way to say that would be that while this book does offer some good code examples, the writing leaves much to be desired, and much better books are out there that cover the same material. The honest assessment is that this book is just a mess. Half the book could be cut and the other half rewritten to better explain things with clearer, non-circular definitions. The only good thing about the book is the code examples, and many of those examples are also redundant, filling the pages of the book with lines of code that the reader has seen multiple times before. This book could have been a third the length and covered the same amount of material.

Even though that last bit was a pretty harsh review, we should still explore what's in the book, if only to see how the breadth of material compares to Professional CUDA C Programming. The first chapter is the normal introduction to the book's material, describing the architecture of a GPU and discussing how parallel programming with this architecture is so different than programming on a CPU. The verbosity of this chapter alone should have been a clue that this book would drag on and on, but I was willing to give it a chance. The next chapter introduces our first real CUDA program with a vector addition kernel. We're still getting started with CUDA C at this point, so I chalk up the authors' overly detailed explanations to taking extra care with novice readers. We end up walking through all of the parts of a working CUDA program, explaining everything in excruciating detail.

The third chapter covers how to work more efficiently with threads and loading data into GPU memory from the CPU with a more complex example of calculating image blur. We also get our first exposure to thread synchronization, something that must be thoroughly understood to program GPUs effectively. This chapter is also where I start to realize how nutty some of the explanations are getting. Here's just one example of them describing how arrays are laid out in memory:
A two-dimensional array can be linearized in at least two ways. One way is to place all elements of the same row into consecutive locations. The rows are then placed one after another into the memory space. This arrangement, called row-major layout, is depicted in Fig. 3.3. To improve readability, we will use Mj,i to denote the M element at the jth row and the ith column. Pj,i is equivalent to the C expression M[j][i] but is slightly more readable. Fig. 3.3 illustrates how a 4×4 matrix M is linearized into a 16-element one-dimensional array, with all elements of row 0 first, followed by the four elements of row 1, and so on. Therefore, the one-dimensional equivalent index for M in row j and column i is j*4 +i. The j*4 term skips all elements of the rows before row j. The i term then selects the right element within the section for row j. The one-dimensional index for M2,1 is 2*4 +1 =9, as shown in Fig. 3.3, where M9 is the one-dimensional equivalent to M2,1. This process shows the way C compilers linearize two-dimensional arrays.
Wow. I'm not sure how a reader that needs this level of detail for understanding how a matrix is arranged in memory is going to understand the memory hierarchy and synchronization issues of GPU programming. This explanation is just too much for a book like this. Readers should already have some knowledge of standard C programming, including multi-dimensional array memory layout, before attempting CUDA programming. I can't imagine learning both at the same time going very well. As for readers who already know how all of this stuff works, they could easily skip every other paragraph and skim the rest to make trudging through these explanations more tolerable.

The next chapter is on how to manage memory and arrange data access to optimize memory usage and bandwidth. We find that memory management is just as, if not more important than thread management for making optimal use of the GPU computing resources, and the book solidifies this understanding through an extended optimization example of a matrix multiplication kernel.

At this point we've learned the fundamentals of GPU programming, so the next chapter moves into more advanced topics in performance optimization with the memory hierarchy and the compute core architecture. Then, chapter six covers number format considerations between integers and single- and double-precision floating point representations. The authors' definition of representable numbers struck me as exceptionally cringe-worthy here:
The representable numbers of a representation format are the numbers that can be exactly represented in the format.
This is but one example of their impenetrable and useless definitions. More often than not, I found that if I hadn't already known what they were talking about, their discussions would provide no further illumination.

Now we get into the halfway decent part of the book, the extended example chapters on parallel patterns. Each of these chapters works through a different example kernel of a particular problem that comes up often in parallel programming, and they introduce additional features of GPU programming that can assist in solving these problems in a more optimal way. The contents of these chapters are as follows:
  • Chapter 7: Convolution
  • Chapter 8: Prefix Sum (Accumulator)
  • Chapter 9: Parallel Histogram Calculation
  • Chapter 10: Sparse Matrix Computation
  • Chapter 11: Merge Sort
  • Chapter 12: Graph Search
As long as you skim the descriptions of the problems and solutions, and focus on understanding the code yourself, these chapters are quite useful examples of how to write performant parallel programs with CUDA. However, the authors continue to suffer from what seems to be a mis-interpretation of the phrase, "a picture is worth a thousand words." For every diagram they use, they also include a thousand words or more of explanation, describing the diagrams ad nauseam. 

The next chapter covers how to kick off kernels from within other kernels in order to enable dynamic parallelism. Up until this point, all kernels have been launched from the host (CPU) code, but it is possible to have kernels launch other kernels to take advantage of additional parallelism while the code is executing on the GPU, an effective feature for some algorithms. Then, the next three chapters are fairly useful application case studies. Like the parallel pattern example chapters, these chapters use CUDA code to show how to take advantage of more advanced features of the GPU, and how to put together everything we've learned so far to optimize some example parallel programs. The applications described are for non-Cartesian MRI, molecular visualization and analysis, and machine learning neural networks, so nice, interesting topics for GPU programming.

The last five chapters were either more drudgery or topics I wasn't interested in, so I skipped them and called it quits for this long and tedious book. For completeness, those chapters are on how to think when parallel programming (so a pep talk on what to think about from authors that couldn't clearly describe much else in the book), multi-GPU programming, OpenACC (another GPU programming framework, like CUDA), still more performance considerations, and a summary chapter. 

I couldn't bring myself to keep reading chapters that wouldn't amount to anything, so I put down the book after finishing the last chapter on application case studies. I found that chapters seven through sixteen contained most of the useful information in the book, but the introduction to CUDA programming was too verbose and confusing. There are much better books out there for learning that part of CUDA programming. Case in point: CUDA by Example or the next book in this review.

Professional CUDA C Programming

Unlike the last book, I was surprised by how readable this book was. The authors did an excellent job of presenting concepts in CUDA programming in a clear, direct, and succinct manner. They also did this without resorting to humor, which can sometimes work if the author is an excellent writer, but it often feels forced and lame when done poorly. It's better to stick to clear descriptions and tight writing, as these authors did quite well. I was actually disappointed that I didn't read this book first, instead saving it until last, because it did the best job of explaining all of the CUDA programming concepts while covering essentially the same material as Programming Massively Parallel Processors and certainly more than CUDA by Example

The first chapter is the obligatory introduction to CUDA with the requisite Hello, World program showing how to run code on the GPU. Right away, we can see how well-written the descriptions are with this discussion of how parallel programming is different than sequential programming:

When implementing a sequential algorithm, you may not need to understand the details of the computer architecture to write a correct program. However, when implementing algorithms for multicore machines, it is much more important for programmers to be aware of the characteristics of the underlying computer architecture. Writing both correct and efficient parallel programs requires a fundamental knowledge of multicore architectures.
We need to be prepared to think differently about problems when parallel programming, and we're going to have to learn the architecture of the underlying hardware to make full use of it. That leads us right into chapter 2, where we learn about the CUDA programming model and how to organize threads on the device, but it doesn't end there. Throughout the book we're learning more and more about the nVidia GPU architecture (specifically the older Fermi and Kepler architectures, since those were available at the time of the book's writing) in order to take full advantage of its compute power. I like how the authors grounded their discussions in specific GPU architectures and showed how the architecture was evolving from one generation to the next. I'm sure the newer Pascal, Volta, and Turing architectures provide more advanced and flexible features, but the book builds a great foundation. Chapter 2 also contains the clearest definition of a kernel that I've seen, yet:
A kernel function is the code to be executed on the device side. In a kernel function, you define the computation for a single thread, and the data access for that thread. When the kernel is called, many different CUDA threads perform the same computation in parallel.
This explanation is the essence of the paradigm shift from sequential to parallel programming, and it's important to understand the effect it has on the code that you write and how it runs on the hardware. In addition to the excellent writing, each chapter has some nice exercises at the end. That's not normally something you find in programming books like this. Exercises seem to be left to textbooks, like Programming Massively Parallel Processors, which had them as well, but in Professional CUDA C Programming they're more well-conceived and more relevant.

The next chapter covers the CUDA execution model, or how the code runs on the real hardware. Here is where we learn how to optimize CUDA programs to take advantage of all of those independent compute cores on the GPU, and this chapter even gets into dynamic parallelism earlier in the book rather than waiting and treating it as a special topic like the last book did.

Chapter 4 covers global memory and chapter 5 looks at shared and constant memory. Understanding the trade-offs of each of these memories is important to getting the maximum performance out of the GPU because most often these programs are memory-bound, not compute-bound. Like everything else, the authors do an excellent job explaining the memory hierarchy and how those trade-offs affect CUDA programs. The examples used throughout the book are simple so that the reader doesn't get bogged down trying to understand unrelated algorithm details. The more complex examples may be thought-provoking, but simple examples do a good job of showcasing the specifics of the topic at hand.

Chapter 6 addresses streams and events, which are used to overlap computation with data transfer. Using streams can partially, or in some cases completely hide the time it takes to get the data into the GPU memory. Chapter 7 explains more optimization techniques by using CUDA instruction-level primitives to directly control how computations are performed on the GPU. These instructions trade some accuracy for speed, and they should be used only if the accuracy is not critical to the application. The authors do a good job of explaining all of the implications here.

The last three chapters weren't as interesting to me, not because I was tired of the book this time, but because they were about the same topics that I skipped in the other CUDA books: OpenACC, multi-GPU programming, and the CUDA development process. The rest of the book was excellent, and far better than the other two CUDA books I read. The writing is clear with plenty of diagrams for better understanding of each topic, and the book organization is done well. If you're interested in GPU programming and want to read one book, this one is it.


Between these two CUDA books, the choice is obvious. Programming Massively Parallel Processors was a bloated dud. It may be worth it just for the large set of example programs it contains, but there are other options coming down the pipeline for that kind of cookbook that may be better. Professional CUDA C Programming was better in every way, and really the book to get for learning CUDA programming. The authors did a great job of explaining complex topics in GPU architecture with concise, understandable writing, relevant diagrams, and appropriate exercises for practice. It's exactly the kind of book I want for learning a new programming language, or in this case, programming paradigm. If you're at all interested in CUDA programming, it's worth checking out.