100% found this document useful (1 vote)
20 views

Download ebooks file Data Parallel C++ Mastering DPC++ for Programming of Heterogeneous Systems using C++ and SYCL 1st Edition James Reinders all chapters

James

Uploaded by

ficcogresszn
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
20 views

Download ebooks file Data Parallel C++ Mastering DPC++ for Programming of Heterogeneous Systems using C++ and SYCL 1st Edition James Reinders all chapters

James

Uploaded by

ficcogresszn
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 55

Download the Full Version of textbook for Fast Typing at textbookfull.

com

Data Parallel C++ Mastering DPC++ for Programming


of Heterogeneous Systems using C++ and SYCL 1st
Edition James Reinders

https://textbookfull.com/product/data-parallel-c-mastering-
dpc-for-programming-of-heterogeneous-systems-using-c-and-
sycl-1st-edition-james-reinders/

OR CLICK BUTTON

DOWNLOAD NOW

Download More textbook Instantly Today - Get Yours Now at textbookfull.com


Recommended digital products (PDF, EPUB, MOBI) that
you can download immediately if you are interested.

Data Parallel C++ Mastering DPC++ for Programming of


Heterogeneous Systems using C++ and SYCL 1st Edition James
Reinders
https://textbookfull.com/product/data-parallel-c-mastering-dpc-for-
programming-of-heterogeneous-systems-using-c-and-sycl-1st-edition-
james-reinders/
textboxfull.com

Handbook of Macroeconomics, Volume 2A-2B SET 1st Edition


John B. Taylor

https://textbookfull.com/product/handbook-of-macroeconomics-
volume-2a-2b-set-1st-edition-john-b-taylor/

textboxfull.com

Catalysis and the Mechanism of Methane Conversion to


Chemicals C C and C O Bonds Formation Using Heterogeneous
Homogenous and Biological Catalysts Toshihide Baba
https://textbookfull.com/product/catalysis-and-the-mechanism-of-
methane-conversion-to-chemicals-c-c-and-c-o-bonds-formation-using-
heterogeneous-homogenous-and-biological-catalysts-toshihide-baba/
textboxfull.com

Programming: Principles and Practice Using C++ , Second


Edition Stroustrup

https://textbookfull.com/product/programming-principles-and-practice-
using-c-second-edition-stroustrup/

textboxfull.com
Programming Principles and Practice Using C 3rd Edition
Stroustrup

https://textbookfull.com/product/programming-principles-and-practice-
using-c-3rd-edition-stroustrup/

textboxfull.com

Problem Solving in Data Structures Algorithms Using C


Programming Interview Guide 1st Edition Hemant Jain

https://textbookfull.com/product/problem-solving-in-data-structures-
algorithms-using-c-programming-interview-guide-1st-edition-hemant-
jain/
textboxfull.com

Pro Tbb: C++ Parallel Programming with Threading Building


Blocks 1st Edition Michael Voss

https://textbookfull.com/product/pro-tbb-c-parallel-programming-with-
threading-building-blocks-1st-edition-michael-voss/

textboxfull.com

Concurrency in C Cookbook Asynchronous Parallel and


Multithreaded Programming 2nd Edition Stephen Cleary

https://textbookfull.com/product/concurrency-in-c-cookbook-
asynchronous-parallel-and-multithreaded-programming-2nd-edition-
stephen-cleary/
textboxfull.com

Programming Principles and Practice Using C Third Edition


Bjarne Stroustrup

https://textbookfull.com/product/programming-principles-and-practice-
using-c-third-edition-bjarne-stroustrup/

textboxfull.com
Data Parallel C++
Mastering DPC++ for Programming of
Heterogeneous Systems using
C++ and SYCL

James Reinders
Ben Ashbaugh
James Brodman
Michael Kinsner
John Pennycook
Xinmin Tian
Data Parallel C++
Mastering DPC++
for Programming
of Heterogeneous Systems
using C++ and SYCL

James Reinders
Ben Ashbaugh
James Brodman
Michael Kinsner
John Pennycook
Xinmin Tian
Data Parallel C++: Mastering DPC++ for Programming of Heterogeneous Systems using
C++ and SYCL
James Reinders Ben Ashbaugh
Beaverton, OR, USA Folsom, CA, USA
James Brodman Michael Kinsner
Marlborough, MA, USA Halifax, NS, Canada
John Pennycook Xinmin Tian
San Jose, CA, USA Fremont, CA, USA

ISBN-13 (pbk): 978-1-4842-5573-5 ISBN-13 (electronic): 978-1-4842-5574-2


https://doi.org/10.1007/978-1-4842-5574-2

Copyright © 2021 by Intel Corporation


This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of the material is concerned,
specifically the rights of translation, reprinting, reuse of illustrations, recitation, broadcasting, reproduction on microfilms or in any other
physical way, and transmission or information storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar
methodology now known or hereafter developed.

Open Access   This book is licensed under the terms of the Creative Commons Attribution 4.0 International
License (http://creativecommons.org/licenses/by/4.0/), which permits use, sharing, adaptation, distribution
and reproduction in any medium or format, as long as you give appropriate credit to the original author(s) and
the source, provide a link to the Creative Commons license and indicate if changes were made.

The images or other third party material in this book are included in the book’s Creative Commons license, unless indicated otherwise in
a credit line to the material. If material is not included in the book’s Creative Commons license and your intended use is not permitted by
statutory regulation or exceeds the permitted use, you will need to obtain permission directly from the copyright holder.

Trademarked names, logos, and images may appear in this book. Rather than use a trademark symbol with every occurrence of a
trademarked name, logo, or image we use the names, logos, and images only in an editorial fashion and to the benefit of the trademark
owner, with no intention of infringement of the trademark.

The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are not identified as such, is not to
be taken as an expression of opinion as to whether or not they are subject to proprietary rights.

Intel, the Intel logo, Intel Optane, and Xeon are trademarks of Intel Corporation in the U.S. and/or other countries. Khronos and the
Khronos Group logo are trademarks of the Khronos Group Inc. in the U.S. and/or other countries. OpenCL and the OpenCL logo are
trademarks of Apple Inc. in the U.S. and/or other countries. OpenMP and the OpenMP logo are trademarks of the OpenMP Architecture
Review Board in the U.S. and/or other countries. SYCL and the SYCL logo are trademarks of the Khronos Group Inc. in the U.S. and/or
other countries.

Software and workloads used in performance tests may have been optimized for performance only on Intel microprocessors.
Performance tests are measured using specific computer systems, components, software, operations and functions. Any change to any of
those factors may cause the results to vary. You should consult other information and performance tests to assist you in fully evaluating
your contemplated purchases, including the performance of that product when combined with other products. For more complete
information visit www.intel.com/benchmarks. Performance results are based on testing as of dates shown in configuration and may not
reflect all publicly available security updates. See configuration disclosure for details. No product or component can be absolutely secure.
Intel technologies’ features and benefits depend on system configuration and may require enabled hardware, software or service
activation. Performance varies depending on system configuration. No computer system can be absolutely secure. Check with your
system manufacturer or retailer or learn more at www.intel.com. Intel’s compilers may or may not optimize to the same degree for
non-Intel microprocessors for optimizations that are not unique to Intel microprocessors. These optimizations include SSE2, SSE3, and
SSSE3 instruction sets and other optimizations. Intel does not guarantee the availability, functionality, or effectiveness of any
optimization on microprocessors not manufactured by Intel. Microprocessor-dependent optimizations in this product are intended for
use with Intel microprocessors. Certain optimizations not specific to Intel microarchitecture are reserved for Intel microprocessors.
Please refer to the applicable product User and Reference Guides for more information regarding the specific instruction sets covered by
this notice. Notice revision #20110804.

While the advice and information in this book are believed to be true and accurate at the date of publication, neither the authors nor the
editors nor the publisher can accept any legal responsibility for any errors or omissions that may be made. The publisher makes no
warranty, express or implied, with respect to the material contained herein.

Managing Director, Apress Media LLC: Welmoed Spahr


Acquisitions Editor: Natalie Pao
Development Editor: James Markham
Coordinating Editor: Jessica Vakili

Distributed to the book trade worldwide by Springer Science+Business Media New York, 1 NY Plaza, New York, NY 10004. Phone
1-800-SPRINGER, fax (201) 348-4505, e-mail orders-ny@springer-sbm.com, or visit www.springeronline.com. Apress Media, LLC is a
California LLC and the sole member (owner) is Springer Science + Business Media Finance Inc (SSBM Finance Inc). SSBM Finance Inc is
a Delaware corporation.

For information on translations, please e-mail booktranslations@springernature.com; for reprint, paperback, or audio rights, please
e-mail bookpermissions@springernature.com.

Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook versions and licenses are also available for
most titles. For more information, reference our Print and eBook Bulk Sales web page at http://www.apress.com/bulk-sales.

Any source code or other supplementary material referenced by the author in this book is available to readers on GitHub via the book’s
product page, located at www.apress.com/978-1-4842-5573-5. For more detailed information, please visit http://www.apress.com/
source-code.
Printed on acid-free paper
Table of Contents
About the Authors�����������������������������������������������������������������������������xvii
Preface����������������������������������������������������������������������������������������������xix
Acknowledgments���������������������������������������������������������������������������xxiii

Chapter 1: Introduction������������������������������������������������������������������������1
Read the Book, Not the Spec��������������������������������������������������������������������������������2
SYCL 1.2.1 vs. SYCL 2020, and DPC++�����������������������������������������������������������������3
Getting a DPC++ Compiler������������������������������������������������������������������������������������4
Book GitHub����������������������������������������������������������������������������������������������������������4
Hello, World! and a SYCL Program Dissection�������������������������������������������������������5
Queues and Actions����������������������������������������������������������������������������������������������6
It Is All About Parallelism��������������������������������������������������������������������������������������7
Throughput������������������������������������������������������������������������������������������������������7
Latency������������������������������������������������������������������������������������������������������������8
Think Parallel���������������������������������������������������������������������������������������������������8
Amdahl and Gustafson������������������������������������������������������������������������������������9
Scaling�������������������������������������������������������������������������������������������������������������9
Heterogeneous Systems��������������������������������������������������������������������������������10
Data-Parallel Programming���������������������������������������������������������������������������11
Key Attributes of DPC++ and SYCL���������������������������������������������������������������������12
Single-Source������������������������������������������������������������������������������������������������12
Host���������������������������������������������������������������������������������������������������������������13
Devices����������������������������������������������������������������������������������������������������������13

iii
Table of Contents

Kernel Code���������������������������������������������������������������������������������������������������14
Asynchronous Task Graphs����������������������������������������������������������������������������15
C++ Lambda Functions���������������������������������������������������������������������������������18
Portability and Direct Programming��������������������������������������������������������������21
Concurrency vs. Parallelism��������������������������������������������������������������������������������22
Summary������������������������������������������������������������������������������������������������������������23

Chapter 2: Where Code Executes��������������������������������������������������������25


Single-Source�����������������������������������������������������������������������������������������������������26
Host Code������������������������������������������������������������������������������������������������������27
Device Code���������������������������������������������������������������������������������������������������28
Choosing Devices������������������������������������������������������������������������������������������������29
Method#1: Run on a Device of Any Type�������������������������������������������������������������30
Queues����������������������������������������������������������������������������������������������������������31
Binding a Queue to a Device, When Any Device Will Do��������������������������������34
Method#2: Using the Host Device for Development and Debugging�������������������35
Method#3: Using a GPU (or Other Accelerators)��������������������������������������������������38
Device Types��������������������������������������������������������������������������������������������������38
Device Selectors��������������������������������������������������������������������������������������������39
Method#4: Using Multiple Devices����������������������������������������������������������������������43
Method#5: Custom (Very Specific) Device Selection������������������������������������������45
device_selector Base Class���������������������������������������������������������������������������45
Mechanisms to Score a Device���������������������������������������������������������������������46
Three Paths to Device Code Execution on CPU���������������������������������������������������46
Creating Work on a Device����������������������������������������������������������������������������������48
Introducing the Task Graph����������������������������������������������������������������������������48
Where Is the Device Code?����������������������������������������������������������������������������50

iv
Table of Contents

Actions�����������������������������������������������������������������������������������������������������������53
Fallback���������������������������������������������������������������������������������������������������������56
Summary������������������������������������������������������������������������������������������������������������58

Chapter 3: Data Management�������������������������������������������������������������61


Introduction���������������������������������������������������������������������������������������������������������62
The Data Management Problem�������������������������������������������������������������������������63
Device Local vs. Device Remote�������������������������������������������������������������������������63
Managing Multiple Memories�����������������������������������������������������������������������������64
Explicit Data Movement���������������������������������������������������������������������������������64
Implicit Data Movement��������������������������������������������������������������������������������65
Selecting the Right Strategy��������������������������������������������������������������������������66
USM, Buffers, and Images�����������������������������������������������������������������������������������66
Unified Shared Memory��������������������������������������������������������������������������������������67
Accessing Memory Through Pointers������������������������������������������������������������67
USM and Data Movement������������������������������������������������������������������������������68
Buffers����������������������������������������������������������������������������������������������������������������71
Creating Buffers��������������������������������������������������������������������������������������������72
Accessing Buffers������������������������������������������������������������������������������������������72
Access Modes�����������������������������������������������������������������������������������������������74
Ordering the Uses of Data�����������������������������������������������������������������������������������75
In-order Queues���������������������������������������������������������������������������������������������77
Out-of-Order (OoO) Queues���������������������������������������������������������������������������78
Explicit Dependences with Events�����������������������������������������������������������������78
Implicit Dependences with Accessors�����������������������������������������������������������80
Choosing a Data Management Strategy��������������������������������������������������������������86
Handler Class: Key Members������������������������������������������������������������������������������87
Summary������������������������������������������������������������������������������������������������������������90

v
Table of Contents

Chapter 4: Expressing Parallelism������������������������������������������������������91


Parallelism Within Kernels����������������������������������������������������������������������������������92
Multidimensional Kernels������������������������������������������������������������������������������93
Loops vs. Kernels������������������������������������������������������������������������������������������95
Overview of Language Features�������������������������������������������������������������������������97
Separating Kernels from Host Code��������������������������������������������������������������97
Different Forms of Parallel Kernels���������������������������������������������������������������98
Basic Data-Parallel Kernels��������������������������������������������������������������������������������99
Understanding Basic Data-Parallel Kernels���������������������������������������������������99
Writing Basic Data-Parallel Kernels������������������������������������������������������������100
Details of Basic Data-Parallel Kernels���������������������������������������������������������103
Explicit ND-Range Kernels��������������������������������������������������������������������������������106
Understanding Explicit ND-Range Parallel Kernels�������������������������������������107
Writing Explicit ND-Range Data-Parallel Kernels����������������������������������������112
Details of Explicit ND-Range Data-Parallel Kernels�������������������������������������113
Hierarchical Parallel Kernels�����������������������������������������������������������������������������118
Understanding Hierarchical Data-Parallel Kernels��������������������������������������119
Writing Hierarchical Data-Parallel Kernels��������������������������������������������������119
Details of Hierarchical Data-Parallel Kernels����������������������������������������������122
Mapping Computation to Work-Items���������������������������������������������������������������124
One-to-One Mapping�����������������������������������������������������������������������������������125
Many-to-One Mapping���������������������������������������������������������������������������������125
Choosing a Kernel Form������������������������������������������������������������������������������������127
Summary����������������������������������������������������������������������������������������������������������129

vi
Table of Contents

Chapter 5: Error Handling�����������������������������������������������������������������131


Safety First��������������������������������������������������������������������������������������������������������132
Types of Errors��������������������������������������������������������������������������������������������������133
Let’s Create Some Errors!���������������������������������������������������������������������������������135
Synchronous Error���������������������������������������������������������������������������������������135
Asynchronous Error�������������������������������������������������������������������������������������136
Application Error Handling Strategy������������������������������������������������������������������138
Ignoring Error Handling�������������������������������������������������������������������������������138
Synchronous Error Handling������������������������������������������������������������������������140
Asynchronous Error Handling����������������������������������������������������������������������141
Errors on a Device���������������������������������������������������������������������������������������������146
Summary����������������������������������������������������������������������������������������������������������147

Chapter 6: Unified Shared Memory���������������������������������������������������149


Why Should We Use USM?��������������������������������������������������������������������������������150
Allocation Types������������������������������������������������������������������������������������������������150
Device Allocations���������������������������������������������������������������������������������������151
Host Allocations�������������������������������������������������������������������������������������������151
Shared Allocations���������������������������������������������������������������������������������������151
Allocating Memory��������������������������������������������������������������������������������������������152
What Do We Need to Know?������������������������������������������������������������������������153
Multiple Styles���������������������������������������������������������������������������������������������154
Deallocating Memory����������������������������������������������������������������������������������159
Allocation Example��������������������������������������������������������������������������������������159
Data Management���������������������������������������������������������������������������������������������160
Initialization�������������������������������������������������������������������������������������������������160
Data Movement�������������������������������������������������������������������������������������������161
Queries��������������������������������������������������������������������������������������������������������������168
Summary����������������������������������������������������������������������������������������������������������170
vii
Table of Contents

Chapter 7: Buffers����������������������������������������������������������������������������173
Buffers��������������������������������������������������������������������������������������������������������������174
Creation�������������������������������������������������������������������������������������������������������175
What Can We Do with a Buffer?������������������������������������������������������������������181
Accessors����������������������������������������������������������������������������������������������������������182
Accessor Creation���������������������������������������������������������������������������������������185
What Can We Do with an Accessor?������������������������������������������������������������191
Summary����������������������������������������������������������������������������������������������������������192

Chapter 8: Scheduling Kernels and Data Movement������������������������195


What Is Graph Scheduling?�������������������������������������������������������������������������������196
How Graphs Work in DPC++�����������������������������������������������������������������������������197
Command Group Actions�����������������������������������������������������������������������������198
How Command Groups Declare Dependences��������������������������������������������198
Examples�����������������������������������������������������������������������������������������������������199
When Are the Parts of a CG Executed?��������������������������������������������������������206
Data Movement�������������������������������������������������������������������������������������������������206
Explicit���������������������������������������������������������������������������������������������������������207
Implicit���������������������������������������������������������������������������������������������������������208
Synchronizing with the Host�����������������������������������������������������������������������������209
Summary����������������������������������������������������������������������������������������������������������211

Chapter 9: Communication and Synchronization�����������������������������213


Work-Groups and Work-Items���������������������������������������������������������������������������214
Building Blocks for Efficient Communication����������������������������������������������������215
Synchronization via Barriers�����������������������������������������������������������������������215
Work-Group Local Memory��������������������������������������������������������������������������217

viii
Table of Contents

Using Work-Group Barriers and Local Memory�������������������������������������������������219


Work-Group Barriers and Local Memory in ND-­Range Kernels�������������������223
Work-Group Barriers and Local Memory in Hierarchical Kernels����������������226
Sub-Groups�������������������������������������������������������������������������������������������������������230
Synchronization via Sub-Group Barriers�����������������������������������������������������230
Exchanging Data Within a Sub-Group����������������������������������������������������������231
A Full Sub-Group ND-Range Kernel Example����������������������������������������������233
Collective Functions������������������������������������������������������������������������������������������234
Broadcast����������������������������������������������������������������������������������������������������234
Votes������������������������������������������������������������������������������������������������������������235
Shuffles�������������������������������������������������������������������������������������������������������235
Loads and Stores�����������������������������������������������������������������������������������������238
Summary����������������������������������������������������������������������������������������������������������239

Chapter 10: Defining Kernels������������������������������������������������������������241


Why Three Ways to Represent a Kernel?����������������������������������������������������������242
Kernels As Lambda Expressions�����������������������������������������������������������������������244
Elements of a Kernel Lambda Expression���������������������������������������������������244
Naming Kernel Lambda Expressions�����������������������������������������������������������247
Kernels As Named Function Objects�����������������������������������������������������������������248
Elements of a Kernel Named Function Object���������������������������������������������249
Interoperability with Other APIs������������������������������������������������������������������������251
Interoperability with API-Defined Source Languages����������������������������������252
Interoperability with API-Defined Kernel Objects����������������������������������������253
Kernels in Program Objects������������������������������������������������������������������������������255
Summary����������������������������������������������������������������������������������������������������������257

ix
Table of Contents

Chapter 11: Vectors��������������������������������������������������������������������������259


How to Think About Vectors������������������������������������������������������������������������������260
Vector Types������������������������������������������������������������������������������������������������������263
Vector Interface�������������������������������������������������������������������������������������������������264
Load and Store Member Functions�������������������������������������������������������������267
Swizzle Operations��������������������������������������������������������������������������������������269
Vector Execution Within a Parallel Kernel���������������������������������������������������������270
Vector Parallelism���������������������������������������������������������������������������������������������274
Summary����������������������������������������������������������������������������������������������������������275

Chapter 12: Device Information��������������������������������������������������������277


Refining Kernel Code to Be More Prescriptive��������������������������������������������������278
How to Enumerate Devices and Capabilities����������������������������������������������������280
Custom Device Selector������������������������������������������������������������������������������281
Being Curious: get_info<>��������������������������������������������������������������������������285
Being More Curious: Detailed Enumeration Code����������������������������������������286
Inquisitive: get_info<>��������������������������������������������������������������������������������288
Device Information Descriptors������������������������������������������������������������������������288
Device-Specific Kernel Information Descriptors�����������������������������������������������288
The Specifics: Those of “Correctness”��������������������������������������������������������������289
Device Queries��������������������������������������������������������������������������������������������290
Kernel Queries���������������������������������������������������������������������������������������������292
The Specifics: Those of “Tuning/Optimization”�������������������������������������������������293
Device Queries��������������������������������������������������������������������������������������������293
Kernel Queries���������������������������������������������������������������������������������������������294
Runtime vs. Compile-Time Properties��������������������������������������������������������������294
Summary����������������������������������������������������������������������������������������������������������295

x
Table of Contents

Chapter 13: Practical Tips����������������������������������������������������������������297


Getting a DPC++ Compiler and Code Samples�������������������������������������������������297
Online Forum and Documentation��������������������������������������������������������������������298
Platform Model�������������������������������������������������������������������������������������������������298
Multiarchitecture Binaries���������������������������������������������������������������������������300
Compilation Model���������������������������������������������������������������������������������������300
Adding SYCL to Existing C++ Programs�����������������������������������������������������������303
Debugging���������������������������������������������������������������������������������������������������������305
Debugging Kernel Code�������������������������������������������������������������������������������306
Debugging Runtime Failures�����������������������������������������������������������������������307
Initializing Data and Accessing Kernel Outputs������������������������������������������������310
Multiple Translation Units����������������������������������������������������������������������������������319
Performance Implications of Multiple Translation Units������������������������������320
When Anonymous Lambdas Need Names��������������������������������������������������������320
Migrating from CUDA to SYCL���������������������������������������������������������������������������321
Summary����������������������������������������������������������������������������������������������������������322

Chapter 14: Common Parallel Patterns���������������������������������������������323


Understanding the Patterns������������������������������������������������������������������������������324
Map�������������������������������������������������������������������������������������������������������������325
Stencil���������������������������������������������������������������������������������������������������������326
Reduction����������������������������������������������������������������������������������������������������328
Scan������������������������������������������������������������������������������������������������������������330
Pack and Unpack�����������������������������������������������������������������������������������������332
Using Built-In Functions and Libraries��������������������������������������������������������������333
The DPC++ Reduction Library���������������������������������������������������������������������334
oneAPI DPC++ Library���������������������������������������������������������������������������������339
Group Functions������������������������������������������������������������������������������������������340

xi
Table of Contents

Direct Programming������������������������������������������������������������������������������������������341
Map�������������������������������������������������������������������������������������������������������������341
Stencil���������������������������������������������������������������������������������������������������������342
Reduction����������������������������������������������������������������������������������������������������344
Scan������������������������������������������������������������������������������������������������������������345
Pack and Unpack�����������������������������������������������������������������������������������������348
Summary����������������������������������������������������������������������������������������������������������351
For More Information�����������������������������������������������������������������������������������351

Chapter 15: Programming for GPUs��������������������������������������������������353


Performance Caveats����������������������������������������������������������������������������������������354
How GPUs Work������������������������������������������������������������������������������������������������354
GPU Building Blocks������������������������������������������������������������������������������������354
Simpler Processors (but More of Them)������������������������������������������������������356
Simplified Control Logic (SIMD Instructions)�����������������������������������������������361
Switching Work to Hide Latency������������������������������������������������������������������367
Offloading Kernels to GPUs�������������������������������������������������������������������������������369
SYCL Runtime Library����������������������������������������������������������������������������������369
GPU Software Drivers����������������������������������������������������������������������������������370
GPU Hardware���������������������������������������������������������������������������������������������371
Beware the Cost of Offloading!��������������������������������������������������������������������372
GPU Kernel Best Practices��������������������������������������������������������������������������������374
Accessing Global Memory���������������������������������������������������������������������������374
Accessing Work-Group Local Memory���������������������������������������������������������378
Avoiding Local Memory Entirely with Sub-Groups��������������������������������������380
Optimizing Computation Using Small Data Types����������������������������������������381
Optimizing Math Functions��������������������������������������������������������������������������382
Specialized Functions and Extensions��������������������������������������������������������382
Summary����������������������������������������������������������������������������������������������������������383
For More Information�����������������������������������������������������������������������������������384

xii
Table of Contents

Chapter 16: Programming for CPUs��������������������������������������������������387


Performance Caveats����������������������������������������������������������������������������������������388
The Basics of a General-Purpose CPU��������������������������������������������������������������389
The Basics of SIMD Hardware���������������������������������������������������������������������������391
Exploiting Thread-Level Parallelism������������������������������������������������������������������398
Thread Affinity Insight���������������������������������������������������������������������������������401
Be Mindful of First Touch to Memory�����������������������������������������������������������405
SIMD Vectorization on CPU��������������������������������������������������������������������������������406
Ensure SIMD Execution Legality������������������������������������������������������������������407
SIMD Masking and Cost������������������������������������������������������������������������������409
Avoid Array-of-Struct for SIMD Efficiency���������������������������������������������������411
Data Type Impact on SIMD Efficiency����������������������������������������������������������413
SIMD Execution Using single_task��������������������������������������������������������������415
Summary����������������������������������������������������������������������������������������������������������417

Chapter 17: Programming for FPGAs������������������������������������������������419


Performance Caveats����������������������������������������������������������������������������������������420
How to Think About FPGAs��������������������������������������������������������������������������������420
Pipeline Parallelism�������������������������������������������������������������������������������������424
Kernels Consume Chip “Area”���������������������������������������������������������������������427
When to Use an FPGA����������������������������������������������������������������������������������������428
Lots and Lots of Work����������������������������������������������������������������������������������428
Custom Operations or Operation Widths������������������������������������������������������429
Scalar Data Flow�����������������������������������������������������������������������������������������430
Low Latency and Rich Connectivity�������������������������������������������������������������431
Customized Memory Systems���������������������������������������������������������������������432
Running on an FPGA�����������������������������������������������������������������������������������������433
Compile Times���������������������������������������������������������������������������������������������435

xiii
Table of Contents

Writing Kernels for FPGAs���������������������������������������������������������������������������������440


Exposing Parallelism�����������������������������������������������������������������������������������440
Pipes������������������������������������������������������������������������������������������������������������456
Custom Memory Systems����������������������������������������������������������������������������462
Some Closing Topics�����������������������������������������������������������������������������������������465
FPGA Building Blocks����������������������������������������������������������������������������������465
Clock Frequency������������������������������������������������������������������������������������������467
Summary����������������������������������������������������������������������������������������������������������468

Chapter 18: Libraries������������������������������������������������������������������������471


Built-In Functions����������������������������������������������������������������������������������������������472
Use the sycl:: Prefix with Built-In Functions������������������������������������������������474
DPC++ Library��������������������������������������������������������������������������������������������������478
Standard C++ APIs in DPC++���������������������������������������������������������������������479
DPC++ Parallel STL�������������������������������������������������������������������������������������483
Error Handling with DPC++ Execution Policies�������������������������������������������492
Summary����������������������������������������������������������������������������������������������������������492

Chapter 19: Memory Model and Atomics�����������������������������������������495


What Is in a Memory Model?����������������������������������������������������������������������������497
Data Races and Synchronization�����������������������������������������������������������������498
Barriers and Fences������������������������������������������������������������������������������������501
Atomic Operations���������������������������������������������������������������������������������������503
Memory Ordering�����������������������������������������������������������������������������������������504
The Memory Model�������������������������������������������������������������������������������������������506
The memory_order Enumeration Class�������������������������������������������������������508
The memory_scope Enumeration Class�����������������������������������������������������511
Querying Device Capabilities�����������������������������������������������������������������������512
Barriers and Fences������������������������������������������������������������������������������������514

xiv
Table of Contents

Atomic Operations in DPC++�����������������������������������������������������������������������515


Using Atomics in Real Life��������������������������������������������������������������������������������523
Computing a Histogram�������������������������������������������������������������������������������523
Implementing Device-Wide Synchronization�����������������������������������������������525
Summary����������������������������������������������������������������������������������������������������������528
For More Information�����������������������������������������������������������������������������������529

Epilogue: Future Direction of DPC++������������������������������������������������531


Alignment with C++20 and C++23�������������������������������������������������������������������532
Address Spaces������������������������������������������������������������������������������������������������534
Extension and Specialization Mechanism���������������������������������������������������������536
Hierarchical Parallelism������������������������������������������������������������������������������������537
Summary����������������������������������������������������������������������������������������������������������538
For More Information�����������������������������������������������������������������������������������539

Index�������������������������������������������������������������������������������������������������541

xv
About the Authors
James Reinders is a consultant with more than three decades of
experience in parallel computing and is an author/coauthor/editor of
ten technical books related to parallel programming. He has had the
great fortune to help make key contributions to two of the world’s fastest
computers (#1 on the TOP500 list) as well as many other supercomputers
and software developer tools. James finished 10,001 days (over 27 years)
at Intel in mid-­2016, and he continues to write, teach, program, and
consult in areas related to parallel computing (HPC and AI).

Ben Ashbaugh is a Software Architect at Intel Corporation where he has


worked for over 20 years developing software drivers for Intel graphics
products. For the past 10 years, Ben has focused on parallel programming
models for general-purpose computation on graphics processors,
including SYCL and DPC++. Ben is active in the Khronos SYCL, OpenCL,
and SPIR working groups, helping to define industry standards for parallel
programming, and he has authored numerous extensions to expose
unique Intel GPU features.

James Brodman is a software engineer at Intel Corporation working


on runtimes and compilers for parallel programming, and he is one of
the architects of DPC++. He has a Ph.D. in Computer Science from the
University of Illinois at Urbana-Champaign.

Michael Kinsner is a Principal Engineer at Intel Corporation developing


parallel programming languages and models for a variety of architectures,
and he is one of the architects of DPC++. He contributes extensively to
spatial programming models and compilers, and is an Intel representative
within The Khronos Group where he works on the SYCL and OpenCL

xvii
About the Authors

industry standards for parallel programming. Mike has a Ph.D. in


Computer Engineering from McMaster University, and is passionate
about programming models that cross architectures while still enabling
performance.
John Pennycook is an HPC Application Engineer at Intel Corporation,
focused on enabling developers to fully utilize the parallelism available
in modern processors. He is experienced in optimizing and parallelizing
applications from a range of scientific domains, and previously served
as Intel’s representative on the steering committee for the Intel eXtreme
Performance User’s Group (IXPUG). John has a Ph.D. in Computer
Science from the University of Warwick. His research interests are varied,
but a recurring theme is the ability to achieve application “performance
portability” across different hardware architectures.

Xinmin Tian is a Senior Principal Engineer and Compiler Architect at Intel


Corporation, and serves as Intel’s representative on OpenMP Architecture
Review Board (ARB). He is responsible for driving OpenMP offloading,
vectorization, and parallelization compiler technologies for current and
future Intel architectures. His current focus is on LLVM-based OpenMP
offloading, DPC++ compiler optimizations for Intel oneAPI Toolkits for
CPU and Xe accelerators, and tuning HPC/AI application performance.
He has a Ph.D. in Computer Science, holds 27 U.S. patents, has published
over 60 technical papers with over 1200 citations of his work, and has co-
authored two books that span his expertise.

xviii
Preface
Address sch
Future

rs
ce ers
ed
uli
USM

sso
Spaces

ls
ng

ac buff
C++

e
rn
ke
ism

host
memory
specialize
queue devices
|
r. |

extend
model
hie

L TH
rar +

SYC PAR INK

lam
SY L
y
libPC+

built-Cin ALL atomics


s

bd
EL
D

as
communication

vectors
7

os nc
Khron
+1

sy
C+

rm
tfo
pla del
GP mo
scan

pack/unpack
U get_info<> data parallelism gather/scatter
ing
gg
bu
mi

de
sc

thread
ma ce

FPGA
pipes

SIMD
u
p

emulator stencil
re d

affinity

This book is about programming for data parallelism using C++. If you are
new to parallel programming, that is okay. If you have never heard of SYCL
or the DPC++ compiler, that is also okay.
SYCL is an industry-driven Khronos standard adding data parallelism
to C++ for heterogeneous systems. DPC++ is an open source compiler
project that is based on SYCL, a few extensions, and broad heterogeneous
support that includes GPU, CPU, and FPGA support. All examples in this
book compile and work with DPC++ compilers.

xix
Preface

If you are a C programmer who is not well versed in C++, you are in
good company. Several of the authors of this book happily admit that we
picked up C++ by reading books that used C++ like this one. With a little
patience, this book should be approachable by C programmers with a
desire to write modern C++ programs.

C
 ontinuing to Evolve
When this book project began in 2019, our vision for fully supporting C++
with data parallelism required a number of extensions beyond the then-­
current SYCL 1.2.1 standard. These extensions, supported by the DPC++
compiler, included support for Unified Shared Memory (USM), sub-
groups to complete a three-level hierarchy throughout SYCL, anonymous
lambdas, and numerous programming simplifications.
At the time that this book is being published (late 2020), a provisional
SYCL 2020 specification is available for public comment. The provisional
specification includes support for USM, sub-groups, anonymous lambdas,
and simplifications for coding (akin to C++17 CTAD). This book teaches
SYCL with extensions to approximate where SYCL will be in the future.
These extensions are implemented in the DPC++ compiler project. While
we expect changes to be small compared to the bulk of what this book
teaches, there will be changes with SYCL as the community helps refine
it. Important resources for updated information include the book GitHub
and errata that can be found from the web page for this book (www.apress.
com/9781484255735), as well as the oneAPI DPC++ language reference
(tinyurl.com/dpcppref ).

xx
Preface

The evolution of SYCL and DPC++ continues. Prospects for the future
are discussed in the Epilogue, after we have taken a journey together to
learn how to use DPC++ to create programs for heterogeneous systems
using SYCL.
It is our hope that our book supports and helps grow the SYCL
community, and helps promote data-parallel programming in C++.

Structure of This Book


It is hard to leap in and explain everything at once. In fact, it is impossible as
far as we know. Therefore, this book is a journey that takes us through what
we need to know to be an effective programmer with Data Parallel C++.
Chapter 1 lays the first foundation by covering core concepts that are
either new or worth refreshing in our minds.
Chapters 2–4 lay a foundation of understanding for data-parallel
programming C++. When we finish with reading Chapters 1–4,
we will have a solid foundation for data-parallel programming in C++.
Chapters 1–4 build on each other, and are best read in order.

Future
c t i ce
In Pra
patterns tips libraries
Ch 13-19 atomics
GPUs
memory models
CPUs FPGAs
ls
Ch 5-12
error handling scheduling
communication vector devices
Detai
ation
Welcome

oF und
to
DPC ++ queue buffer USM
Ch 1-4 accessor kernel

xxi
Preface

Chapters 5–19 fill in important details by building on each other


to some degree while being easy to jump between if desired. The book
concludes with an Epilogue that discusses likely and possible future
directions for Data Parallel C++.
We wish you the best as you learn to use SYCL and DPC++.

James Reinders
Ben Ashbaugh
James Brodman
Michael Kinsner
John Pennycook
Xinmin Tian
October 2020

xxii
Acknowledgments
We all get to new heights by building on the work of others. Isaac Newton
gave credit for his success from “standing on the shoulders of giants.” We
would all be in trouble if this was not allowed.
Perhaps there is no easy path to writing a new book on an exciting new
developments such as SYCL and DPC++. Fortunately, there are good people
who make that path easier—it is our great joy to thank them for their help!
We are deeply thankful for all those whose work has helped make this
book possible, and we do wish to thank as many as we can recall by name.
If we stood on your shoulders and did not call you out by name, you can
know we are thankful, and please accept our apologies for any accidental
forgetfulness.
A handful of people tirelessly read our early manuscripts and provided
insightful feedback for which we are very grateful. These reviewers include
Jefferson Amstutz, Thomas Applencourt, Alexey Bader, Gordon Brown,
Konstantin Bobrovsky, Robert Cohn, Jessica Davies, Tom Deakin, Abhishek
Deshmukh, Bill Dieter, Max Domeika, Todd Erdner, John Freeman, Joe
Garvey, Nithin George, Milind Girkar, Sunny Gogar, Jeff Hammond,
Tommy Hoffner, Zheming Jin, Paul Jurczak, Audrey Kertesz, Evgueny
Khartchenko, Jeongnim Kim, Rakshith Krishnappa, Goutham Kalikrishna
Reddy Kuncham, Victor Lomüller, Susan Meredith, Paul Petersen, Felipe
De Azevedo Piovezan, Ruyman Reyes, Jason Sewall, Byron Sinclair,
Philippe Thierry, and Peter Žužek.
We thank the entire development team at Intel who created DPC++
including its libraries and documentation, without which this book would
not be possible.

xxiii
Acknowledgments

The Khronos SYCL working group and Codeplay are giants on


which we have relied. We share, with them, the goal of bringing effective
and usable data parallelism to C++. We thank all those involved in the
development of the SYCL specification. Their tireless work to bring forward
a truly open standard for the entire industry is to be admired. The SYCL
team has been true to its mission and desire to keep this standard really
open. We also highly appreciate the trailblazing work done by Codeplay, to
promote and support SYCL before DPC++ was even a glimmer in our eyes.
They continue to be an important resource for the entire community.
Many people within Intel have contributed extensively to DPC++ and
SYCL—too many to name here. We thank all of you for your hard work,
both in the evolution of the language and APIs and in the implementation
of prototypes, compilers, libraries, and tools. Although we can’t name
everyone, we would like to specifically thank some of the key language
evolution architects who have made transformative contributions to
DPC++ and SYCL: Roland Schulz, Alexey Bader, Jason Sewall, Alex
Wells, Ilya Burylov, Greg Lueck, Alexey Kukanov, Ruslan Arutyunyan, Jeff
Hammond, Erich Keane, and Konstantin Bobrovsky.
We appreciate the patience and dedication of the DPC++ user
community. The developers at Argonne National Lab have been incredibly
supportive in our journey together with DPC++.
As coauthors, we cannot adequately thank each other enough. We
came together in early 2019, with a vision that we would write a book to
teach SYCL and DPC++. Over the next year, we became a team that learned
how to teach together. We faced challenges from many commitments that
tried to pull us away from book writing and reviewing, including product
deadlines and standards work. Added to the mix for the entire world was
COVID-19. We are a little embarrassed to admit that the stay-at-home
orders gave us a non-trivial boost in time and focus for the book. Our
thoughts and prayers extend to all those affected by this global pandemic.

xxiv
Acknowledgments

James Reinders: I wish to thank Jefferson Amstutz for enlightening


discussions of parallelism in C++ and some critically useful help to get
some C++ coding straight by using Jefferson’s superpower as C++ compiler
error message whisperer. I thank my wife, Susan Meredith, for her love,
support, advice, and review. I am grateful for those in Intel who thought
I would enjoy helping with this project and asked me to join in the fun!
Many thanks to coauthors for their patience (with me) and hard work on
this ambitious project.
Ben Ashbaugh: I am grateful for the support and encouragement of my
wife, Brenna, and son, Spencer. Thank you for the uninterrupted writing
time, and for excuses to go for a walk or play games when I needed a break!
To everyone in the Khronos SYCL and OpenCL working groups, thank you
for the discussion, collaboration, and inspiration. DPC++ and this book
would not be possible without you.
James Brodman: I thank my family and friends for all their support.
Thanks to all my colleagues at Intel and in Khronos for great discussions
and collaborations.
Michael Kinsner: I thank my wife, Jasmine, and children, Winston and
Tilly, for their support during the writing of this book and throughout
the DPC++ project. Both have required a lot of time and energy, and I
wouldn’t have been able to do either without so much support. A thank
you also goes to many people at Intel and Khronos who have poured their
energy and time into SYCL and DPC++. All of you have shaped SYCL,
OpenCL, and DPC++ and have been part of the countless discussions and
experiments that have informed the thinking leading to DPC++ and this
book.
John Pennycook: I cannot thank my wife, Louise, enough for her patience,
understanding, and support in juggling book writing with care of our
newborn daughter, Tamsyn. Thanks also to Roland Schulz and Jason
Sewall for all of their work on DPC++ and their assistance in making sense
of C++ compiler errors!

xxv
Acknowledgments

Xinmin Tian: I appreciate Alice S. Chan and Geoff Lowney for their
strong support during the writing of the book and throughout the DPC++
performance work. Sincere thanks to Guei-Yuan Lueh, Konstantin
Bobrovsky, Hideki Saito, Kaiyu Chen, Mikhail Loenko, Silvia Linares, Pavel
Chupin, Oleg Maslov, Sergey Maslov, Vlad Romanov, Alexey Sotkin, Alexey
Sachkov, and the entire DPC++ compiler and runtime and tools teams for
all of their great contributions and hard work in making DPC++ compiler
and tools possible.
We appreciate the hard work by the entire Apress team, including the
people we worked with directly the most: Natalie Pao, Jessica Vakili,
C Dulcy Nirmala, and Krishnan Sathyamurthy.
We were blessed with the support and encouragement of some special
managers, including Herb Hinstorff, Bill Savage, Alice S. Chan, Victor Lee,
Ann Bynum, John Kreatsoulas, Geoff Lowney, Zack Waters, Sanjiv Shah,
John Freeman, and Kevin Stevens.
Numerous colleagues offered information, advice, and vision. We
are sure that there are more than a few people whom we have failed to
mention who have positively impacted this book project. We thank all
those who helped by slipping in their ingredients into our book project.
We apologize to all who helped us and were not mentioned here.
Thank you all, and we hope you find this book invaluable in your
endeavors.

xxvi
CHAPTER 1

Introduction
L TH
SYC PAR INK

lam
ALL

bd
EL

as
7

os
Khron
+1
C+

This chapter lays the foundation by covering core concepts, including


terminology, that are critical to have fresh in our minds as we learn how to
accelerate C++ programs using data parallelism.
Data parallelism in C++ enables access to parallel resources in
a modern heterogeneous system. A single C++ application can use
any combination of devices—including GPUs, CPUs, FPGAs, and AI
Application-Specific Integrated Circuits (ASICs)—that are suitable to the
problems at hand.
This book teaches data-parallel programming using C++ and SYCL.
SYCL (pronounced sickle) is an industry-driven Khronos standard that
adds data parallelism to C++ for heterogeneous systems. SYCL programs
perform best when paired with SYCL-aware C++ compilers such as the
open source Data Parallel C++ (DPC++) compiler used in this book. SYCL
is not an acronym; SYCL is simply a name.

© Intel Corporation 2021 1


J. Reinders et al., Data Parallel C++, https://doi.org/10.1007/978-1-4842-5574-2_1
Chapter 1 Introduction

DPC++ is an open source compiler project, initially created by Intel


employees, committed to strong support of data parallelism in C++.
The DPC++ compiler is based on SYCL, a few extensions,1 and broad
heterogeneous support that includes GPU, CPU, and FPGA devices. In
addition to the open source version of DPC++, there are commercial
versions available in Intel oneAPI toolkits.
Implemented features based on SYCL are supported by both the open
source and commercial versions of the DPC++ compilers. All examples
in this book compile and work with either version of the DPC++ compiler,
and almost all will compile with recent SYCL compilers. We are careful
to note where extensions are used that are DPC++ specific at the time of
publication.

Read the Book, Not the Spec


No one wants to be told “Go read the spec!” Specifications are hard to
read, and the SYCL specification is no different. Like every great language
specification, it is full of precision and light on motivation, usage, and
teaching. This book is a “study guide” to teach SYCL and use of the DPC++
compiler.
As mentioned in the Preface, this book cannot explain everything at
once. Therefore, this chapter does what no other chapter will do: the code
examples contain programming constructs that go unexplained until
future chapters. We should try to not get hung up on understanding the
coding examples completely in Chapter 1 and trust it will get better with
each chapter.

1
 he DPC++ team is quick to point out that they hope all their extensions will be
T
considered, and hopefully accepted, by the SYCL standard at some time in the
future.

2
Chapter 1 Introduction

SYCL 1.2.1 vs. SYCL 2020, and DPC++


As this book goes to press, the provisional SYCL 2020 specification is
available for public comments. In time, there will be a successor to
the current SYCL 1.2.1 standard. That anticipated successor has been
informally referred to as SYCL 2020. While it would be nice to say that this
book teaches SYCL 2020, that is not possible because that standard does
not yet exist.
This book teaches SYCL with extensions, to approximate where SYCL
will be in the future. These extensions are implemented in the DPC++
compiler project. Almost all the extensions implemented in DPC++ exist
as new features in the provisional SYCL 2020 specification. Notable new
features that DPC++ supports are USM, sub-­groups, syntax simplifications
enabled by C++17 (known as CTAD—class template argument deduction),
and the ability to use anonymous lambdas without having to name them.
At publication time, no SYCL compiler (including DPC++) exists that
implements all the functionality in the SYCL 2020 provisional specification.
Some of the features used in this book are specific to the DPC++
compiler. Many of these features were originally Intel extensions to
SYCL that have since been accepted into the SYCL 2020 provisional
specification, and in some cases their syntax has changed slightly during
the standardization process. Other features are still being developed or are
under discussion for possible inclusion in future SYCL standards, and their
syntax may similarly be modified. Such syntax changes are actually highly
desirable during language development, as we want features to evolve
and improve to address the needs of wider groups of developers and the
capabilities of a wide range of devices. All of the code samples in this book
use the DPC++ syntax to ensure compatibility with the DPC++ compiler.
While endeavoring to approximate where SYCL is headed, there will
almost certainly need to be adjustments to information in this book to
align with the standard as it evolves. Important resources for updated

3
Another Random Scribd Document
with Unrelated Content
avowal. She knew nothing about it. But for this intimate death, she
prepared to take revenge on her son whom she loved, and on her
son’s loved woman.
My father lighted his cigar, and as usual sagged into the ease of his
wife’s will.
“I put you through eight years of college,” he began. He examined
his Corona. He moistened a finger and applied it to a crack in the
rich black leaf. “Some day you’ll get all we have. If you want some
cash—up to five thousand—it’s yours. What more have you got the
right to ask? If you marry, like every other married man, you got to
look out for yourself.” He puffed slowly: more rapidly, as a thought at
last came to his assistance. “I suppose your mother and I should
move to a shoddy flat, so you and Harry Fayn’s daughter can live in
a swell one? You’ll buy our motor, I guess?... Why, when I was your
age, my father——”
I did not argue. I did not point out to him the false exaggeration of his
picture. I did not show him that at my age his work had been to help
his father invest his money so that neither of them should ever need
to use their minds: that indeed neither of them had ever used their
minds, and that the fair consequence had been ... so far beyond the
ugliness of their thoughts ... that I was able wholly, passionately,
greatly, to give all my mind, all my life to the white flame of
intellectual creation. But even this flame needed its nourishment:
was it logical to bring this light to being and then let it die? The gross
man is nourished with gross food: the indifferent man with any food
at all. My high work called for high fuel. Not for a drudge, not for a
harried woman, nor a pretty one, nor for promiscuous pleasures. For
Mildred! the essential Mildred! Nothing less. And the proof was that
ere I had found the perfection of her love, I had not been nourished
at all. Rather than blemish the fine growth of my life, I had lived on
myself, until I had found my equal....
Of all this, I said naught. I kissed my mother’s accurately rouged
cheek: I touched my father’s hand, its soft complacence gave me a
savage turn. I went quickly to the door.
My mother stopped me.
“John, I want you to come back. Are you free Saturday? ... in the
afternoon? I’ll stay at home. Nothing has been decided. You must
not be hasty. I want to see——”
I saw them: so impervious and healthy.—From their stubbornness,
my will: from their sheer animal strength, my mental power.... So
flashed my thought, but not in irony: a cool constatation.
I said:
“There is nothing for you to see. It doesn’t matter. And everything
has been decided.”
... I was in the street. And I had forgotten my words, impetuous,
boastful words that seemed to mean nothing at all. For in my
consciousness there was the knowledge that nothing had been
decided: that my great need of winning Mildred and of having her
right was farther from fulfillment than it had ever been.—Better go
back, and not be proud: win your mother, said my reason. I knew I
would not go back.

c
I HAD left early, too early to rush precipitate to Mildred. There was
time to walk to her, and in the blind congestion of my thoughts the
need of walking.
Spring was a haze within the quiet street. The houses were high
gray walls of emptiness. Their windows told of no life. Life was a
fertile hush dreaming inchoate like a stirless sea against these rocks
of houses. I walked as through some elemental birth, æons anterior
to men and cities; through sleepy and vast densities scarce sparked
with consciousness. A monster too dull to be savage, too close still
to the protoplasmic slime, was this Spring world sprawled upon the
stone hills of the city. And as I walked within its palpable mood, my
own thoughts clashed like cymbals in a night: their strident clarities
were like a wound gashed in its somnolent flesh.
My thoughts stood apart from the city, and from myself, and from
each other. I knew that I had come to a crisis in my years. I needed
Mildred and I needed my work. To forego my impecunious glory
upon the laboratory battlefield meant death. To fail of Mildred
seemed to mean death, also. How could I have them both? I had not
even wooed her. Her brilliant being stood beyond any touch or any
claim of mine. Had she been a woman whom I could bind with
sentimental promise or engage with the zest of fighting with me
toward a dim future, she had not been Mildred. She was alive,
gloriously, luminously alive. Like a flame she spent herself in the day,
and she might be gone to-morrow. Even now, I could not tell but
there was possibly another’s love to fuel her. But even if she could
wait, could I? I knew at last the desperate price of my abstaining
years. There was stored up in me a might of energy, continent,
compressed, and the fire touched it. I was fire—a white totality of
active hunger, kindling, devouring in a moment the years’
accumulated burden. I needed Mildred; and needed her perfectly;
and needed her at once. I could not take her hidden, meanly, without
killing my great need ere its fulfillment. All the ways of an inherited
culture had this night for me their reason. Beauty and amenity of
place, the lovely stuffs wealth has created for its homes and bodies
... I saw them all as acolytes of my essential worship. Mildred stood
helpless like a goddess: no man dared take her without the fullest
raiment and the richest music, and a fair temple built to flesh her
spirit. Such were the exalted symbols of my sense, but my thoughts
were shrewd. This perfect child was of the modern world. To snatch
her away would be to blemish her. What the world could bring to
make an harmonious matrix for her life with me, in no way changing
her, was the instant need. Marriage ... a home. All else had been
violence rather than fruition: a gesture like that of a crazed man who
mars his love in the impotence of desire.
But what hope was there? Why as I walked through the high Spring-
flushed night did I not walk in despair? My mother was the
implacable foe of Mildred and in her hand was a weapon she had
already with sure instinct wielded. And Mildred herself: what reason
had I to believe that she would love me, wed me ... even if the way
were clear? We were friends. I had soon won from her the clear note
of her laughter. But her laughter surely was no hidden grace that I
alone could win.
She herself was the rare thing, and that all life responded to her, that
life’s common stuff was by her alchemied into her gold. Since she
was perfect, why should she receive within herself the
transfigurement of love, the translation of marriage? Mildred must
have many friends, many loves, for she was virginal not by deprival
but as a young birch is white. She was intelligent; her mind had a
luminous response to every phase of the world that touched her
own. Her intelligence lived inseparate within her senses, within her
milk-pale skin. But even so, could I imagine that she would have
responded to the mute beginnings of my glory? What was I in her
eyes? A quiet man, young, fair-haired, with deep gray eyes, not tall:
evidently gifted, evidently strong; a man who stood at the bottom
rung of a mysterious ladder that led to esoteric formulæ about the
stuffs and ways of human brains. That much she might know. Could
she, for all her pure intelligence, know how my science was to be a
Dionysian dance: an heroic poem in which I marshaled the
harmonies of nature, as once did Æschylus with his Prometheus, or
the old Jew with his Job? Could she know that? and could I tell her
that? Psychologist: what a prosy lie the word would give her! Oh, I
had faith in myself and faith in Mildred. But how could I hope that she
was ready to come to me knowing me her equal, as I knew her my
own?
—I should despair, I should despair!
And yet I did not. I walked with bright thoughts through the soft
fluxed night, and the defeat with my parents, the uncertainty of what
lay beyond, did not make me despair. Indeed my chances of battle
did not hold my thoughts. I walked in an exhilarant and scattered
mood as if the battle was already won, and I could disband my army!
—Life is good. Why do I think this now? Because of death. We are at
war with death. In the conflict, misery and hesitancy die. Joy only
lives. Life is good, not because life is good but because we battle
death. Blessed is the foe, for he makes us blessed to ourselves. This
quiet street is quiet because just beyond is the clatter of Broadway.
Lights there jerk in a shallow panic, therefore this strip of sky
between the houserows deepens its gray blue. And the man who
passes: he is a soft and reticent word of flesh because he is within
stone lips of houses, because he moves from clamor.... Mildred:
what will I say to her to-night? ... why have I thought of death? I go to
Mildred whom my life loves; and I think of death, and I learn that it is
the strangeness and the nearness of death which makes life real!
I see a baby boy: he is in the street, he has been struck and badly
hurt by a stone. His sister, scarcely larger than himself, leads him
across the gutter, screaming, homeward. Toddling howling mite! His
tears hold rage, fear, protest, pain—no thought of death, no
questioning of life. No, he is wholly alive: life is not good to him, nor
does he love it: fatefully and wholly he accepts it. For he thinks not of
death. Life may be anger and agony and hunger, but it is everything.
—Why then does life seem marvelous to me, save that death must
be near? Mildred...? What if she is death and wooing her, life wooes
its end? and this be the reason why in love life seems so marvelous
good? O Mildred, if this is death, let death enfold me. If you are
death, hurry me to your flame-nothing beside which life—green hills
and creatures swarming in the sun—is a gray sleep. You are not
death, my love. You are the golden trumpet calling me to life.
I see other things. Walking toward Mildred, I see the city. Mildred
colors the whole strange story: that I am alive, that I am I, now
strange! And being strange, all is real, all is inevitable. The real is
mysteriously new! Mildred in everything. She has unfolded and
become the world. Yet in this ecstasy of clearness, I cannot even
know if she is life—or death!
But I do know how this city is a shell: how life floods beyond it: a
cracked shell, the city, so that in little eddies life seeps in.
My vision seeps in, also. I am in a maze of pictures. Mildred has
released me from herself to a bewildering freedom.
I can fly where I will, and enter where I want. I see myriad women’s
arms, suddenly free and fragile like their hair. Women’s arms wave,
like hair, in a great wind. A wind sweeps my maze of images: I see
streaming men and children and women. Each is crouched close to
another. They do not see how they, are streaming, streaming. They
think of themselves as fixed, all else as moving.
But I am moving. Something in me is fixed, and something in me is
moving!...

This is a pleasant room, and I am in it.


What room? Perhaps I am in my house with Mildred, and I am to
have a study generous like this one. Am I in my own future, then?
Where am I if this is my own book-lined study? Where is Mildred?
Let me look sharp and wait. Someone is there....
The room is high and long. Two windows in one wall let in the
budding tree-tops of a square. The other walls rise in dark shelves,
open with books. Against the black of the wood, the plaster wall is
white.
A Tanagra spots it: a Chinese painting: a little rustic jar that seems
Etruscan or may be from Peru. Someone is there. Not I. I am not
looking, in this torrent maze, on my own future. For the man is not I.
He is dark. The lamp, blue Persian with a silk turret-shade clouded
like ivory, shadows half his face, a long and from the forehead
tapering face, and lights an eye that looks up now from his book. The
black hair curls on the forehead in a rounded bang: like one of the
saints on the great Porch at Chartres. A noble face: the nose is
straight and the mouth warm-lipped and large. Brow and curled hair
give saintliness, the nose is resolute and the mouth is subtle. A
variance of authority. He rises. He is tall. His eyes become attentive
and less thoughtful. A regal man, now at his ease in his home, in the
negligee of a moire braided jacket. There is someone else just come
into the room. The clear blue of the eyes is questioning. Can this
someone else be I? What folly! Yet, if I can see this meditative man,
why should he not see me? What a vague mass is the newcomer. I
feel, rather than know it for another man. If I look square for this new
presence, I shall lose the master of the room.—Watch the master
close! The sharp question in his eyes hardens at this other in the
room, as at some ominous intruder. Immobile his face: he reaches
out a hand. His eyes do not lower to what is in his hand. I feel his
hand flex and relax and drop what was in it. Only his eyes are clear,
gazing at this other in the room: and yet straight at me, as if they
gazed at me! The eyes fill with bitterness, with horror that grows
fixed and leaves his eyes.... They die in resignation ... and their
horror creeps now over my own flesh. His hands fly above his head:
so very empty, so very white and tremulous his hands. A knife in his
breast. And all is gone....

... Flowing rivers of faces, of lives saying: “We are steadfast, we are
solid,” as they stream and faint. Now, the familiar blank before my
eyes. The normal street ... I smile at my fancy. I laugh aloud, walking
now commonly. I call to my relief my easy rational knowledge.
“No wonder if to-night you suffer from an erratic gush of energy.
Hyperæsthesia. Here is Mildred’s house. This confidence ... call it
euphoria, for that talk with your parents was a blow, no doubt. Go
ahead. A mastering passion is right to admit no doubt. Bad names
can’t spoil the splendor of my sureness. Go ahead. Win her. What
lies beyond this radiant mist? Go on.”
I rang the bell and gave my hat and coat to the calming butler.

d
THAT moment with the butler in the hall was like a strip of arid land
parting two seas of my mind. As I went up the stairs, all that had
lived in me, walking through the city, went ... went out, and I lived
whole in the imminent presence of Mildred. If I had asked myself
what I had thought, what I had seen, out there, I could have
answered only: Mildred. But even to have asked the question would
have been impossible to me, since every question and every answer
now was Mildred.
She opened, closed the door. Mildred is in the room, with her hand
still on the doorknob and her eyes smiling upon me. Mildred I know
and following my eyes I find at last myself, and still find only Mildred.
Let her stay there smiling, her slight shoulders faintly straining back
with her arms, and the bare throat pulsant. Let her stay there holding
me in her smile. For when she moves, what will become of me? Her
chin is up: her face is inclined forward so that her violet eyes lie
under the half-shut lids and peer at me. Her chin is a rounded,
exquisite apex, and the cheeks trace triangularly subtle to the brow
that is her chiefest glory. Mildred’s hair is gold, and is banded high,
freeing all her forehead.
Let her stay there smiling, holding me in her smile. With her arms’
strain as they clasp the knob behind them, the shoulders are sheer
in the orange gauze of the gown: and the little breasts are high and
firm ... very high, and strangely one with the throb of her throat!
Mildred comes forward and gives me both her hands. Her arms are
thin, they have no molded beauty. They are like all her body: no
sculptured mass of flesh but a mysterious stream of life swift-
running, like white fire ever within itself, yet fixed upon some pattern
immobile and essenced.
“Well,” comes her laughing voice. “You’re early. And you’re out of
breath. If you were late that’d be more excusable. Sit down.”
I sit down, and I stand again.
“Mildred, I’m sorry I am out of breath. But I have breath enough to
say what must come first of all this evening ... first of all, all my life.
Mildred, I love you.”
Her eyes deepen and grow soft. Her delicate face is a hard fragility
about the brooding thought of her eyes. She sits down.
“Come,” she says in a voice that is like her eyes even as before it
had been like her face. “Sit down beside me, John. Here.”
She leads me, holding my hand. When I am beside her on the couch
her hand lifts from mine as if it had been kissed.
“You mean,” she said, “that you love me really, John? that you want
me to live with you, John?”
“I want you to be my wife.”
“Does that mean, you are sure you love only me? That you will never
want to live with another woman?”
My eyes gave her my answer: she saw in them, also, my surprise at
her questions. She went blithely on.
“Could you love me, John, and also sometimes still love someone
else?”
“It might be, Mildred. But in that case I would not now pray as I do,
that you may become my wife.”
She looked down at my hand and her little fist beat on it softly.
“How am I to know?”
“Mildred, know what...?”
“If you said to me: ‘Give me a kiss,’ I would kiss you for I feel like
that. If you said to me: ‘Come with me for a week,’ I would say yes,
for I think that for a week I could be sure that I would feel that way ...
and if I did not, why a week comes to a close. But no man asks me
that! No man tries to kiss me. They all say: ‘Mildred, I love you. I
shall always love you. I want you for my wife.’ That means forever
and ever. You are all so sure. How can I be sure?”
“Will you give me a kiss, Mildred?”
She leaned forward and her lips were faintly parted. My mouth
touched hers, and my eyes saw within her gown her perfect breasts
like porcelain cups, red-tipped.... She was straight again and smiling.
I hid my face in my arms, fighting to master the storm that her cold
lips had loosed.
“John ... did my kiss hurt you, then?”
“No, Mildred. But I suffer. You are so perfect and so brave: and you
feel nothing.”
“That is not so! I liked your kiss.”
“Mildred, beside the anguish and the joy that I feel, you feel nothing.”
She held my hand in her two palms.
“Tell me what to do.”
“Believe in me, Mildred.”
“Why, I do believe in you!”
“Above all else ... above all others.”
“Why? Why must it be only you?”
“Because that is love, Mildred. Because I could not bear it any other
way. Because the death of not having you would be as nothing
beside the death of sharing you even with another’s thought.
Because only in the unity, in the solitary oneness of two souls can
love live.”
Mildred shook her head, and her gold curls rang about her ears.
“You talk like someone else. Yes,” she faced me, “someone who
loves me, too, and wants me whole and for always and can’t bear
any other eyes but his own looking upon me. Someone else whose
wishes I’d obey reasonably, John, as I obeyed yours, when you said:
‘Give me a kiss.’” Her eyes were cool and happy despite their
problem. “But he doesn’t ask reasonable things. He wants me
forever and ever. How can I promise him that? And how can I
promise him what I can’t give him at once?”
“Who is he, Mildred?” I forced the words and they came like gray
ghosts out of my mouth.
“Oh, you don’t know him. I’ve known him long. And he’s wonderful,
too. Like you are. But different. In every way, different. You don’t,”
she smiled, “encroach on each other at all. He’s big and dark, and
rather slow. And you are wonderfully quick. He is a poet and smells
always of pipe tobacco. His hands are gnarled....”
“He loves you.”
“I think as much as you do, John. His words are strangely like yours,
even though he himself is so different. That is important, is it not? He
asked me one reasonable thing ... one thing I could do.”
“What was that, Mildred?”
“To come to his rooms.”
“Mildred!”
“He has a lovely place down on Washington Square. I supposed,
when he had me there, he’d want to kiss me. But no ... he’s
unreasonable, just like you. He frightened me. He left me so alone. I
was almost chilly, I assure you. With his pacing up and down: saying
‘I love you. I want you. I love you,’ and not even taking my hand.”
She reached for mine. “You see,” she smiled, “he is even less
reasonable than you. You at least kissed me.”
I was up from the couch. She had held my hand. I snatched it from
her. I began to pace, till the thought came that he had done this. I
stopped and faced her. I pulled her up and held her in my arms. I
covered her face with kisses. I found her throat in my dazed ecstasy;
I pressed my mouth within the gauze of her gown. Her cool hand
stopped me, and she held me off.
“No,” she said. “No, I cannot.”
“Why? If you mean what you said. Why?”
Her eyes took on a serious dark question: and I knew how right I was
to love her for the splendor of her chastity. For ere she answered
me, she was seeking deep within her soul the reason, the quiet
reason.
In that true moment when with head bowed she went within herself
to give me answer why she had denied me, I knew the greatness of
my love, and how she was greater than I, and how my sultry passion
had been an ugly shred tangenting from my love.
“Mildred,” I said in her silence, “you will give your answer. But in your
search I can tell you already that you were right; even for my sake, in
the light of my own love, you were right to hold me off. You cannot be
taken that way. You cannot be stormed. Mating with you must be the
peaceful meeting of two equal wills. And it must come to be within a
quiet deep and great like itself. There is a passionate stillness more
powerful than any tempest. I shall not kiss you again, my love, until
you know that kiss for the threshold to our life.”
Her eyes were heavy with thinking. They grew bright.
“Then you agree, even in that, with Philip!”
I nodded. I could not hate him when his name, whoever he was,
lived on her lips.
“And now I can tell you why I pushed you off.”
“Why, Mildred?”
She moved her head slowly from side to side; she sat down; she
smoothed her gown downward from her neck.
“I have learned something ... here.” Her hands with a sharp candor,
while her eyes met mine, followed the gauze I had ruffled, and
cupped her breasts. “I care for you, and I care for Philip. I thought
that was enough: that I could blindly let time order ... time and mood
... what each of you wanted of me, and what I wanted to give. It is
not so. Time counts terribly! Before I can give myself to either of you,
I must know which of you I want to take me first. And then I feel ... I
feel, when I have learned who is first, there may be no second!”
“Mildred, you see that I was right? You have learned what I knew
when I first saw you. Before I saw you I held myself for you. I denied
myself. Not only did I know there could be no one beyond you ...
none even before you!”
She was murmuring almost to herself: “It was your mouth on my
breast. Your hot mouth marking my flesh, that made me know....”
“You would have hated me, were it not I....”
She shook her head: “Philip might have kissed me. How should I
know?”
I smiled. “There is no hurry, dear. Wait. I shall be patient. Wait.”
She hid her face a moment in her hands. And lifting them again, her
eyes laughed hard and strong in her fragile face.
“Oh, patience! Bother patience! Why should we wait? Why can’t we
know now? I want to know. If Philip were only here, I’d know soon
enough. The others don’t count. Really ... how wonderfully simple
when there are only two. And you call for patience. Timid! I’ll phone
for Philip. Yes, I will. If he’s home, I’ll phone and I’ll go over there: or
have him come here quick.... You really should meet him.” Her smile
was above malice. “And I’ll know perhaps, just if I look at him.”
She danced toward the door. There was a knock that stopped her.
She moved slowly, suddenly transfigured, and turned the knob. A
maid stood hesitant.
“Miss Fayn, it’s something urgent, Miss. Your father would like to
speak to you just a minute.”
Mildred looked at me. There was a pallor over the bloom of her
cheeks. Her eyes still danced, unknowing, within an invading pallor. I
was alone.

A stillness lay within the room that had rung and sung with the
dancing laughter of Mildred. Mildred was gone: and someone else is
here! Who is here, blighting this room? I stand and feel a horror rise
from my loins like a gray cloud ... up, up my sides it crawls: lifting my
hair it passes. I forced myself to look over each shoulder: nothing. It
is gone. What is it that was here and that I have not seen and that I
felt I knew? A foul dark mass in the shrine of Mildred’s room. But the
horror that scudded through me is away. Thoughts come. Good
thoughts. Chasing all others.—Mildred is mine, is mine! And she is
wonderful beyond my wonder.
... She opened the door and I shuddered for on her face was the
darkness that had been alone with me.
“Oh,” came her voice, reed-like and stripped. “Oh, he is dead.”
I looked my amazed question: knew I was looking it.
—Your father? Not your father?
“You never saw Philip LaMotte.”
“Never.”
“You will never see him. Nor I, again.”
From within her eyes the shadow came to me and awoke my skin
once more to the familiar horror.
“He is dead.”
I was silent.
“They telephoned my father. Papa and he were friends. Philip has
been murdered!”
I saw her, saw above all my transcendant need of her like a new
radiance within her body. The bewildered cloud upon her face of
sorrow was an intruder, a foe.
—You are mine. All else is trampled out in the march of my love....
She would not have it so. She stood there sorrowing. I took her
hand, and her touch said: “He is murdered.” It was a film, viscous
between us.
But still I could say nothing. I held her hand: I dared not loose it just
because it said: “He is murdered.” Why should I be downed by that?
Whether it helped or no what did it avail against my mastering need?
But the touch of her limp hand spoke, spoke again. My clasp fought
vainly, drawing in the foe, in the attempt to shut him out. Mildred
withdrew her hand, and left in mine the word of her own:
“Philip is murdered.”
I forced myself to say: “I will leave you, love. I cannot help you now.
You will want to be alone.”
She nodded and her eyes avoided mine.
“It is terrible,” she spoke in a voice strangely casual and high. “Who
could have murdered Philip? Sweet, gentle Philip. Great Philip. I am
all dazed. We spoke of murder in his room, that day.”
“You spoke of murder?”
“Philip said to me: ‘You are the woman for whom man kills. I could kill
for you, Mildred.’”
“Dear, even the past is drawn into the dark design of an event that
sweeps us. Philip was rich——?”
“I know.” She did not like my reasoning. “I am dazed. I want to go to
bed ... and to sleep. Leave me, John.”
Still her eyes kept from my own. She had been glorious in my need
of her. Now shattered and distraught with the shadow on her
fragrance, she was almost ugly. Her arms were thin as she twisted
her hands together and her neck was long: and her eyes drooped
heavy down.
—Why is she ugly? I did not love her less. The ugliness I felt was a
pain added to the joy of loving her. And then, a dim sense came. It
was to grow ever less dim.—She is befouled with a thought! And that
thought is my own. She has been fair like a dawn with the dawn of
my love and now my thought clouds her.
—Why is she dark? Because this murder will concern me!... So
much I knew an instant, and forgot. I left her.

e
I AM home. The lamp reveals my study, sharp: a changeling! White
curtains in the deep-set latticed windows, shelves of books, the
couch right angle to the open hearth, the low gray ceiling ... nothing
is moved yet everything is changed. A glow like fever hushes in the
shadow, the dull familiar things swell with vibrance into a dimension
new like an omen.
I sit down, carefully folding my coat.—No wonder. What a shock!
What a night. I huddle in my dressing gown and greet the smoke of
my pipe.—No wonder. I take my book.
—Better read.
Above my shoulder, as I sit with the lamp close on the plain pine
table is a separate shelf: books on astrology. The book I hold is
bound in ivory parchment, cracked: the Gothic type stands bold on
the soft paper.
I begin to read where only yesterday I placed my mark. Yesterday
and this page: to-day and this page again. How can such difference
meet upon a page? But why so whole a difference? What has
happened? Your parents—nothing definitive there. Nothing is lost
there, surely. What you anticipated was: what is anticipated, is. Make
them understand. There is a way, if not to make them understand, at
least to make them.... This sense of an abysmal separateness in
your eye trying to link the words upon the page with words an eye of
yours saw yesterday, could not be born of what happened with your
parents. Philip—what of that? When he was a danger, you did not
know of him: now that you know of him, he is dead. The danger is
dead. She did not yet love him. He made claim upon her, my one
rival claim: and life has withdrawn it for me. A shock—she will need
time—but she will recover! Did this murder shake her whom he loved
as much as me who never saw him? Why not be glad then, if she be
not too shaken? Do you want her prostrate? What folly is this in your
will? Are the gifts of event less welcome than the gifts of nature?
Aren’t you glad you have a body and a mind welcome to Mildred?
Don’t you accept whatever vantage they give you? Why not accept
the vantage of events? How can you help accept? John Mark, will
you be morbid, like other men, when the sun and moon of life shine
full on you?... Better read.
—If there is something in all this, this strangeness in you: something
beside the tumult of your love, and the shock of learning how close
to your desire was another hand, hot and touching your own as you
reached—if there is something else, you’ll see it clearer in the
morning. Don’t push your clarity. Let it ripen. Dangerously close his
hand to your own? It is gone.... He may not be dead? ... a wound?
No, he is murdered. And that is forever.
—Mildred is strangely dim. My memory and the note of my taut
nerves tell me best at this moment how I love her. I want to see her. I
want to have her vividly here. To corroborate what? I want to see
again that first time when I saw her....
Evening, a dance. The electric lamps drive a stiff flood of light
through the gold-paneled room. No air—this atmosphere is a harsh
painted substance. Men and women are brittle or are cloying: their
spirit is dark as if no air had ever entered them. The music is a
weave of stuffs contorted, writhed, a hypocritical plea for gayety: its
sinuous lies move through the hall and through the bodies of the
dancers with a false laughter, with a macabre rhythm. Cynic music,
substitute in this world for breath; as are the lamps for light.... And
the coupled forms jerking slow in its rugose waves.
Then, I see Mildred! I have met her before: casually, more than once.
Now, for the first time, there is the grace in me to see her!
She is air, open and coursing: she is sunlight. Her solidity is resilient.
She has a body which is a luminous smile, impervious and ruthless.
“What are you doing here?” I ask her. For her antithesis is so exact
... the velvety music, the slow whining bodies ... that she is clear like
a poem in a world of inarticulations.
“Let’s talk,” she says. “It will be good for you to talk. Your mood is so
heavy.”
“What are you doing here?”
“Where else did you expect to find me?”
“I expected to find you nowhere.”
“Then you don’t know who I am.”
“You are Mildred Fayn. I have seen you: and I have heard of you.”
“Well, then? Did you not hear that I dance, that I motor, that I ride?
Did you not hear that I flirt?”
“Whatever I heard and saw has naught to do with you.”
“You look, Doctor Mark, as if you had made a discovery. And you
look solemn.”
“I am pleased.”
“You are like a child, perhaps? Most solemn when most pleased?”
“Children have the gift of discovery—and of wonder.”
Suddenly she was serious. She had glanced dazzlingly around me.
Now it was as if she came straight forward.
“I’ll dare be ‘serious’ with you,” she murmured.
She looked full at me: her eyes had a crisp tenderness, like some
immortal fruit ever upon the Springlike verge of ripeness. I knew that
she understood, although the words perhaps were not within her
mind, how laughter is oblique: how seriousness is the full face of joy.
We sat in a little bower cut off from the hall by palms. It became a
cool and fluid haven from the hall—from the hall’s synthetic sun. She
was quiet. She folded her frail hands in her lap and raised her head.
A smile flickered at her mouth like a butterfly at a fruit. She dispelled
it.
“It’s hard to sit serious,” she whispered.
“It is so revealing.”
Again, instantly, she understood.
“Yes: we don’t mind being naked when we are in motion. It must be
that motion covers us? The dance, the swim. But being still, and
being seen....”
“Laughter,” I said, “is a shift we wear like motion.”
There was a pause. I illogically broke it: “You are uncovered, yet you
are at ease.”
She laughed: “No! You are wrapping me up in your observations
about me.”
“Why do they cover, rather than reveal you?”
“Why? Because they are illusions.”
“Oh!”
“Aren’t they romantic and inaccurate? You see, I am a girl who
dances and motors and flirts.” Her smile was indulgent: as if she
invited me, knowing how hard it was, to candor.
“How can you expect me to know you so swiftly?”
“Why not—swiftly?” she said.
I was aware of her as if she had been naked. I leaned forward in my
chair: she lay back in hers, with an ankle poised upon the other. She
knew my awareness, and was unashamed. There was naught
sensual in my knowing her. She did not challenge my sense: she
challenged my understanding. Her emerald dress gleamed in fluid
angles over her hips, around her waist and breast. She was not
naked, after all: she was clad in a cool flame aura of which her eyes
were the measureless sources.
“I am going to leave you here,” I said at last. “I want to see you
again. You will let me see you again?”—Again, again! oh, forever,
shouted my heart. “But not again in that lewd place, with its plush
music and its sticky light.”
“Where?” she asked. My violence was beyond her. She did not think
of the dance as anything but pleasant. And the music was to her the
usual dance music.
“In your home.”
“Come, surely,” she agreed. She gave me her hand.
I had many words, and she had none. My words were my ignorance:
her wisdom was itself, needing no concepts. In that moment, I
learned that also words—like motions—were shifts of
incompleteness. I grew ambitious as I had never been before. Long I
had willed to be great as men are great. And since I had first seen
her on this night I had dared to want her, as man possesses woman.
Now I longed more vertiginously far: I longed to be able to achieve
the domain beyond words, beyond conscious acts—to exert the
wisdom of power, somehow, beyond the articulation of my mind;
even as she was wise in the absolute miracle of her thoughtless
body. So fragile, so profoundly luminous she was! her eyes, her face,
her form the entexture of a petal in which all immensity lay glowing.
—To be a man is misery! Yet to hold her, I must be a man. I
understood the wisdom of beauty, its undimensioned power: and
how intellect and words are its groveling slaves. I envied this girl, I
with my man’s mind. I resolved to equal her in her own high
domain....

But now I cannot even see her! Though I recount this scene, it
sleeps pale in my mind. And if she come at all, it is otherwise than in
her relevation of the world beyond our conscious words—it is as I
saw her last, diminished and blemished by a thought of my own!
—Is this why my love of her dims? Tides ... the energy that swells my
love (do not torment yourself) has ebbed into other harbors, for an
hour. Were this not so, life would grow stagnant in my love, and my
love grow foul like a hooded and shut pool. You must understand
this, always, Mildred (what do you not understand?): how the waters
of my life move out from you, and then move in on you replenished
with the verdance of their wanderings....—Better not think of her
now, nor of the man murdered, nor of the hard enameled cheek of
mother.—Better read....
Like all else in my life, the study in the pseudo-science of astrology is
at once joy in my life and design in my work. I strive, as man has
always striven, to drown this anguish of being born a man, within the
stars. I cannot. For the stars are not greater, truer than my passions;
their convolutions do not make my thoughts petty and unrelated; nor
are they closer to God than my own searching will. The solace of lies
is denied me. All my life has battled against the ease of falsity and
sentiment. The solace of the Truth——?
Oh, I am small indeed, small and imperfect: no stronger and no
greater than those whirling stars. But if they swing sure (an instant)
in balance of the truth, cannot I? Gravitation—it is a phase of will, a
phase of fragmentary conscience, making these stars swing true,
one with the other. Let my thoughts do likewise!
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.

Let us accompany you on the journey of exploring knowledge and


personal growth!

textbookfull.com

You might also like