CUDA is a difficult topic to write about. Parallel programming is complicated even without operating system considerations (Windows, Linux, MacOS), platform considerations (major CUDA architecture version, integrated and discrete GPUs, multiple GPUs), CPU/GPU concurrency considerations, and CUDA-specific considerations such as the need to decide between using the CUDA runtime or the driver API. When you add in the complexities of how best to structure CUDA kernels, it may seem overwhelming.
To present this complexity in a manageable way, most topics are explained more than once, from different perspectives. What does the texture mapping hardware do? is a different question than how do I write a kernel that does texture mapping?, and the book addresses both questions in separate sections. Asynchronous memory copy operations can be explained in several different contexts: the interactions between software abstractions (for example, that participating host memory must be pinned), different hardware implementations, API support for the feature, and optimization strategies. Readers sometimes may wish to consult the index and read all of the different presentations on a given topic.
Optimization guides are like advice columns: too often, the guidance is offered without enough context to be applied meaningfully, and they often seem to contradict themselves. That observation isn’t intended to be pejorative; it’s just a symptom of the complexity of the problem. It has been at least 20 years since blanket generalizations could be made about CPU optimizations, and GPUs are more complicated to program; so it’s unrealistic to expect CUDA optimization advice to be simple.
Additionally, GPU Computing is a sufficiently new enterprise that GPU architects, let alone developers, are still learning how best to program them. For CUDA developers, the ultimate arbiter is usually performance, and performance is usually measured in wall clock time! Recommendations on grid and block sizes, how and when to use shared memory, how many results to compute per thread, and the implications of occupancy on performance should be confirmed empirically by implementing different approaches and measuring the performance of each.