Full Download Parallel programming: concepts and practice 1st Edition - eBook PDF PDF DOCX
Full Download Parallel programming: concepts and practice 1st Edition - eBook PDF PDF DOCX
com
https://ebookluna.com/download/parallel-programming-
concepts-and-practice-ebook-pdf/
OR CLICK HERE
DOWLOAD NOW
https://ebookluna.com/download/an-introduction-to-parallel-
programming-ebook-pdf/
ebookluna.com
https://ebookluna.com/product/ebook-pdf-parallel-computer-
organization-and-design/
ebookluna.com
https://ebookluna.com/product/ebook-pdf-parallel-computer-
organization-and-design-2/
ebookluna.com
https://ebookluna.com/download/data-science-concepts-and-practice-
ebook-pdf/
ebookluna.com
Problem Solving and Python Programming 1st edition - eBook
PDF
https://ebookluna.com/download/problem-solving-and-python-programming-
ebook-pdf/
ebookluna.com
https://ebookluna.com/product/ebook-pdf-community-and-human-services-
concepts-for-practice/
ebookluna.com
https://ebookluna.com/product/ebook-pdf-introduction-to-leadership-
concepts-and-practice-4th-edition/
ebookluna.com
https://ebookluna.com/product/introduction-to-leadership-concepts-and-
practice-4th-edition-ebook-pdf/
ebookluna.com
https://ebookluna.com/product/ebook-pdf-professional-nursing-practice-
concepts-and-perspectives-7th-edition/
ebookluna.com
Parallel Programming
Parallel Programming
Concepts and Practice
Bertil Schmidt
Institut für Informatik
Staudingerweg 9
55128 Mainz
Germany
Jorge González-Domínguez
Computer Architecture Group
University of A Coruña
Edificio área científica (Office 3.08), Campus de Elviña
15071, A Coruña
Spain
Christian Hundt
Institut für Informatik
Staudingerweg 9
55128 Mainz
Germany
Moritz Schlarb
Data Center
Johannes Gutenberg-University Mainz
Germany
Anselm-Franz-von-Bentzel-Weg 12
55128 Mainz
Germany
Morgan Kaufmann is an imprint of Elsevier
50 Hampshire Street, 5th Floor, Cambridge, MA 02139, United States
Copyright © 2018 Elsevier Inc. All rights reserved.
No part of this publication may be reproduced or transmitted in any form or by any means, electronic or mechanical, including
photocopying, recording, or any information storage and retrieval system, without permission in writing from the publisher. Details on
how to seek permission, further information about the Publisher’s permissions policies and our arrangements with organizations such as
the Copyright Clearance Center and the Copyright Licensing Agency, can be found at our website: www.elsevier.com/permissions.
This book and the individual contributions contained in it are protected under copyright by the Publisher (other than as may be noted
herein).
Notices
Knowledge and best practice in this field are constantly changing. As new research and experience broaden our understanding, changes
in research methods, professional practices, or medical treatment may become necessary.
Practitioners and researchers must always rely on their own experience and knowledge in evaluating and using any information,
methods, compounds, or experiments described herein. In using such information or methods they should be mindful of their own safety
and the safety of others, including parties for whom they have a professional responsibility.
To the fullest extent of the law, neither the Publisher nor the authors, contributors, or editors, assume any liability for any injury and/or
damage to persons or property as a matter of products liability, negligence or otherwise, or from any use or operation of any methods,
products, instructions, or ideas contained in the material herein.
ISBN: 978-0-12-849890-3
Parallelism abounds. Nowadays, any modern CPU contains at least two cores, whereas some CPUs
feature more than 50 processing units. An even higher degree of parallelism is available on larger sys-
tems containing multiple CPUs such as server nodes, clusters, and supercomputers. Thus, the ability
to program these types of systems efficiently and effectively is an essential aspiration for scientists,
engineers, and programmers. The subject of this book is a comprehensive introduction to the area of
parallel programming that addresses this need. Our book teaches practical parallel programming for
shared memory and distributed memory architectures based on the C++11 threading API, Open Mul-
tiprocessing (OpenMP), Compute Unified Device Architecture (CUDA), Message Passing Interface
(MPI), and Unified Parallel C++ (UPC++), as well as necessary theoretical background. We have in-
cluded a large number of programming examples based on the recent C++11 and C++14 dialects of
the C++ programming language.
This book targets participants of “Parallel Programming” or “High Performance Computing”
courses which are taught at most universities at senior undergraduate level or graduate level in com-
puter science or computer engineering. Moreover, it serves as suitable literature for undergraduates in
other disciplines with a computer science minor or professionals from related fields such as research
scientists, data analysts, or R&D engineers. Prerequisites for being able to understand the contents
of our book include some experience with writing sequential code in C/C++ and basic mathematical
knowledge.
In good tradition with the historic symbiosis of High Performance Computing and natural science,
we introduce parallel concepts based on real-life applications ranging from basic linear algebra rou-
tines over machine learning algorithms and physical simulations but also traditional algorithms from
computer science. The writing of correct yet efficient code is a key skill for every programmer. Hence,
we focus on the actual implementation and performance evaluation of algorithms. Nevertheless, the
theoretical properties of algorithms are discussed in depth, too. Each chapter features a collection of
additional programming exercises that can be solved within a web framework that is distributed with
this book. The System for Automated Code Evaluation (SAUCE) provides a web-based testing en-
vironment for the submission of solutions and their subsequent evaluation in a classroom setting: the
only prerequisite is an HTML5 compatible web browser allowing for the embedding of interactive
programming exercise in lectures. SAUCE is distributed as docker image and can be downloaded at
https://parallelprogrammingbook.org
This website serves as hub for related content such as installation instructions, a list of errata, and
supplementary material (such as lecture slides and solutions to selected exercises for instructors).
If you are a student or professional that aims to learn a certain programming technique, we advise to
initially read the first three chapters on the fundamentals of parallel programming, theoretical models,
and hardware architectures. Subsequently, you can dive into one of the introductory chapters on C++11
Multithreading, OpenMP, CUDA, or MPI which are mostly self-contained. The chapters on Advanced
C++11 Multithreading, Advanced CUDA, and UPC++ build upon the techniques of their preceding
chapter and thus should not be read in isolation.
ix
x Preface
If you are a lecturer, we propose a curriculum consisting of 14 lectures mainly covering applications
from the introductory chapters. You could start with a lecture discussing the fundamentals from the
first chapter including parallel summation using a hypercube and its analysis, the definition of basic
measures such as speedup, parallelization efficiency and cost, and a discussion of ranking metrics. The
second lecture could cover an introduction to PRAM, network topologies, weak and strong scaling.
You can spend more time on PRAM if you aim to later discuss CUDA in more detail or emphasize
hardware architectures if you focus on CPUs. Two to three lectures could be spent on teaching the
basics of the C++11 threading API, CUDA, and MPI, respectively. OpenMP can be discussed within
a span of one to two lectures. The remaining lectures can be used to either discuss the content in the
advanced chapters on multithreading, CUDA, or the PGAS-based UPC++ language.
An alternative approach is splitting the content into two courses with a focus on pair-programming
within the lecture. You could start with a course on CPU-based parallel programming covering selected
topics from the first three chapters. Hence, C++11 threads, OpenMP, and MPI could be taught in full
detail. The second course would focus on advanced parallel approaches covering extensive CUDA
programming in combination with (CUDA-aware) MPI and/or the PGAS-based UPC++.
We wish you a great time with the book. Be creative and investigate the code! Finally, we would be
happy to hear any feedback from you so that we could improve any of our provided material.
Acknowledgments
This book would not have been possible without the contributions of many people.
Initially, we would like to thank the anonymous and few non-anonymous reviewers who com-
mented on our book proposal and the final draft: Eduardo Cesar Galobardes, Ahmad Al-Khasawneh,
and Mohammad Olaimat.
Moreover, we would like to thank our colleagues who thoroughly peer-reviewed the chapters and
provided essential feedback: André Müller for his valuable advise on C++ programming, Robin Kobus
for being a tough code reviewer, Felix Kallenborn for his steady proofreading sessions, Daniel Jünger
for constantly complaining about the CUDA chapter, as well as Stefan Endler and Elmar Schömer for
their suggestions.
Additionally, we would like to thank the staff of Morgan Kaufman and Elsevier who coordinated
the making of this book. In particular we would like to mention Nate McFadden.
Finally, we would like to thank our spouses and children for their ongoing support and patience
during the countless hours we could not spend with them.
xi
CHAPTER
INTRODUCTION
Abstract
1
In the recent past, teaching and learning of parallel programming has become increasingly important
due to the ubiquity of parallel processors in portable devices, workstations, and compute clusters. Stag-
nating single-threaded performance of modern CPUs requires future computer scientists and engineers
to write highly parallelized code in order to fully utilize the compute capabilities of current hardware
architectures. The design of parallel algorithms, however, can be challenging especially for inexpe-
rienced students due to common pitfalls such as race conditions when concurrently accessing shared
resources, defective communication patterns causing deadlocks, or the non-trivial task of efficiently
scaling an application over the whole number of available compute units. Hence, acquiring parallel
programming skills is nowadays an important part of many undergraduate and graduate curricula.
More importantly, education of concurrent concepts is not limited to the field of High Performance
Computing (HPC). The emergence of deep learning and big data lectures requires teachers and stu-
dents to adopt HPC as an integral part of their knowledge domain. An understanding of basic concepts
is indispensable for acquiring a deep understanding of fundamental parallelization techniques.
The goal of this chapter is to provide an overview of introductory concepts and terminologies in parallel
computing. We start with learning about speedup, efficiency, cost, scalability, and the computation-to-
communication ratio by analyzing a simple yet instructive example for summing up numbers using a
varying number of processors. We get to know about the two most important parallel architectures:
distributed memory systems and shared memory systems. Designing efficient parallel programs re-
quires a lot of experience and we will study a number of typical considerations for this process such
as problem partitioning strategies, communication patterns, synchronization, and load balancing. We
end this chapter with learning about current and past supercomputers and their historical and upcoming
architectural trends.
Keywords
Parallelism, Speedup, Parallelization, Efficiency, Scalability, Reduction, Computation-to-communica-
tion ratio, Distributed memory, Shared memory, Partitioning, Communication, Synchronization, Load
balancing, Task parallelism, Prefix sum, Deep learning, Top500
CONTENTS
1.1 Motivational Example and Its Analysis ............................................................................ 2
The General Case and the Computation-to-Communication Ratio..................................... 8
1.2 Parallelism Basics .................................................................................................... 10
Distributed Memory Systems................................................................................ 10
Shared Memory Systems..................................................................................... 11
• Speedup. You have designed a parallel algorithm or written a parallel code. Now you want to
know how much faster it is than your sequential approach; i.e., you want to know the speedup.
The speedup (S) is usually measured or calculated for almost every parallel code or algorithm and
is simply defined as the quotient of the time taken using a single processor (T (1)) over the time
measured using p processors (T (p)) (see Eq. (1.1)).
T (1)
S= (1.1)
T (p)
• Efficiency and cost. The best speedup you can usually expect is a linear speedup; i.e., the maximal
speedup you can achieve with p processors or cores is p (although there are exceptions to this,
which are referred to as super-linear speedups). Thus, you want to relate the speedup to the number
of utilized processors or cores. The Efficiency E measures exactly that by dividing S by P (see
Eq. (1.2)); i.e., linear speedup would then be expressed by a value close to 100%. The cost C is
similar but relates the runtime T (p) (instead of the speedup) to the number of utilized processors
(or cores) by multiplying T (p) and p (see Eq. (1.3)).
S T (1)
E= = (1.2)
p T (p) × p
C = T (p) × p (1.3)
• Scalability. Often we do not only want to measure the efficiency for one particular number of pro-
cessors or cores but for a varying number; e.g. P = 1, 2, 4, 8, 16, 32, 64, 128, etc. This is called
scalability analysis and indicates the behavior of a parallel program when the number of processors
increases. Besides varying the number of processors, the input data size is another parameter that
you might want to vary when executing your code. Thus, there are two types of scalability: strong
scalability and weak scalability. In the case of strong scalability we measure efficiencies for a vary-
ing number of processors and keep the input data size fixed. In contrast, weak scalability shows the
behavior of our parallel code for varying both the number of processors and the input data size; i.e.
when doubling the number of processors we also double the input data size.
• Computation-to-communication ratio. This is an important metric influencing the achievable
scalability of a parallel implementation. It can be defined as the time spent calculating divided by
the time spent communicating messages between processors. A higher ratio often leads to improved
speedups and efficiencies.
1.1 MOTIVATIONAL EXAMPLE AND ITS ANALYSIS 3
The example we now want to look at is a simple summation; i.e., given an array A of n numbers we
want to compute n−1
i=0 A[i]. We parallelize this problem using an array of processing elements (PEs).
We make the following (not necessarily realistic) assumptions:
• Computation. Each PE can add two numbers stored in its local memory in one time unit.
• Communication. A PE can send data from its local memory to the local memory of any other PE
in three time units (independent of the size of the data).
• Input and output. At the beginning of the program the whole input array A is stored in PE #0. At
the end the result should be gathered in PE #0.
• Synchronization. All PEs operate in lock-step manner; i.e. they can either compute, communicate,
or be idle. Thus, it is not possible to overlap computation and communication on this architecture.
Speedup is relative. Therefore, we need to establish the runtime of a sequential program first. The
sequential program simply uses a single processor (e.g. PE #0) and adds the n numbers using n − 1
additions in n − 1 time units; i.e. T (1, n) = n − 1. In the following we illustrate our parallel algorithm
for varying p, where p denotes the number of utilized PEs. We further assume that n is a power of 2;
i.e., n = 2k for a positive integer k.
• p = 2. PE #0 sends half of its array to PE #1 (takes three time units). Both PEs then compute the
sum of their respective n/2 numbers (takes time n/2 − 1). PE #1 sends its partial sum back to PE
#0 (takes time 3). PE #0 adds the two partial sums (takes time 1). The overall required runtime is
T (2, n) = 3 + n/2 − 1 + 3 + 1. Fig. 1.1 illustrates the computation for n = 1024 = 210 , which has
a runtime of T (2, 1024) = 3 + 511 + 3 + 1 = 518. This is significantly faster than the sequential
runtime. We can calculate the speedup for this case as T (1, 1024)/T (2, 1024) = 1023/518 = 1.975.
This is very close to the optimum of 2 and corresponds to an efficiency of 98.75% (calculated
dividing the speedup by the number of utilized PEs; i.e. 1.975/2).
• p = 4. PE #0 sends half of the input data to PE #1 (takes time 3). Afterwards PE #0 and PE #1
each send a quarter of the input data to PE #2 and PE #3 respectively (takes time 3). All four PEs
then compute the sum of their respective n/4 numbers in parallel (takes time n/4 − 1). PE #2 and
PE #3 send their partial sums to PE #0 and PE #1, respectively (takes time 3). PE #0 and PE #1
add their respective partial sums (takes time 1). PE #1 then sends its partial sum to PE #0 (takes
time 3). Finally, PE #0 adds the two partial sums (takes time 1). The overall required runtime is
T (4, n) = 3 + 3 + n/4 − 1 + 3 + 1 + 3 + 1. Fig. 1.2 illustrates the computation for n = 1024 = 210 ,
which has a runtime of T (4, 1024) = 3 + 3 + 255 + 3 + 1 + 3 + 1 = 269. We can again calculate the
speedup for this case as T (1, 1024)/T (4, 1024) = 1023/269 = 3.803 resulting in an efficiency of
95.07%. Even though this value is also close to 100%, it is slightly reduced in comparison to p = 2.
The reduction is caused by the additional communication overhead required for the larger number
of processors.
• p = 8. PE #0 sends half of its array to PE #1 (takes time 3). PE #0 and PE #1 then each send a
quarter of the input data to PE #2 and PE #3 (takes time 3). Afterwards, PE #0, PE #1, PE #2, and
PE #3 each send a 1/8 of the input data to PE #5, PE #6, PE #7, and PE #8 (takes again time 3).
Fig. 1.3 illustrates the three initial data distribution steps for n = 1024 = 210 . All eight PEs then
compute the sum of their respective n/8 numbers (takes time n/8 − 1). PE #5, PE #6, PE #7, and
PE #8 send their partial sums to PE #0, PE #1, PE #2, and PE #3, respectively (takes time 3).
4 CHAPTER 1 INTRODUCTION
FIGURE 1.1
Summation of n = 1024 numbers on p = 2 PEs: (A) initially PE #0 stores the whole input data locally; (B) PE #0
sends half of the input to PE #1 (takes time 3); (C) Each PE sums up its 512 numbers (takes time 511);
(D) PE #1 sends its partial sum back to PE #0 (takes time 3); (E) To finalize the computation, PE #0 adds the
two partial sums (takes time 1). Thus, the total runtime is T (2, 1024) = 3 + 511 + 3 + 1 = 518.
Subsequently, PE #0, PE #1, PE #2, and PE #3 add their respective partial sums (takes time 1). PE
#2 and PE #3 then send their partial sums to PE #0 and PE #1, respectively (takes time 3). PE #0
and PE #1 add their respective partial sums (takes time 1). PE #1 then sends its partial sum to PE #0
(takes time 3). Finally, PE #0 adds the two partial sums (takes time 1). The overall required runtime
is T (8, n) = 3 + 3 + 3 + n/8 − 1 + 3 + 1 + 3 + 1 + 3 + 1. The computation for n = 1024 = 210
thus has a runtime of T (8, 1024) = 3 + 3 + 3 + 127 + 3 + 1 + 3 + 1 + 3 + 1 = 148. The speedup
for this case is T (1, 1024)/T (8, 1024) = 1023/148 = 6.91 resulting in an efficiency of 86%. The
decreasing efficiency is again caused by the additional communication overhead required for the
larger number of processors.
We are now able to analyze the runtime of our parallel summation algorithm in a more general way
using p = 2q PEs and n = 2k input numbers:
FIGURE 1.2
Summation of n = 1024 numbers on p = 4 PEs: (A) initially PE #0 stores the whole input in its local memory;
(B) PE #0 sends half of its input to PE #1 (takes time 3); (C) PE #0 and PE #1 send half of their data to PE #2
and PE #3 (takes time 3); (D) Each PE adds its 256 numbers (takes time 255); (E) PE #2 and PE #3 send their
partial sums to PE #0 and PE #1, respectively (takes time 3). Subsequently, PE #0 and PE #1 add their
respective partial sums (takes time 1); (F) PE #1 sends its partial sum to PE #0 (takes time 3), which then
finalizes the computation by adding them (takes time 1). Thus, the total runtime is
T (4, 1024) = 3 + 3 + 511 + 3 + 1 + 3 + 1 = 269.
6 CHAPTER 1 INTRODUCTION
FIGURE 1.3
The three initial data distribution steps for n = 1024 and p = 8: (A) Initially PE #0 stores the whole input in its
local memory and sends half of its input to PE #1; (B) PE #0 and PE #1 send half of their (remaining) data to
PE #2 and PE #3; (C) PE #0, PE #1, PE #2, and PE #3 each send half of their (remaining) input data to PE #5,
PE #6, PE #7, and PE #8.
Fig. 1.4 shows the runtime, speedup, cost, and efficiency of our parallel algorithm for n = 1024
and p ranging from 1 to 512. This type of runtime analysis (where the input size is kept constant
and the number of PEs is scaled) is called strong scalability analysis. We can see that the efficiency
1.1 MOTIVATIONAL EXAMPLE AND ITS ANALYSIS 7
FIGURE 1.4
Strong scalability analysis: runtime, speedup, cost, and efficiency of our parallel summation algorithm for
adding n = 1024 numbers on a varying number of PEs (ranging from 1 to 512).
is high for a small number of PEs (i.e. p n), but is low for a large number of PEs (i.e. p ≈ n).
This behavior can also be deduced from Eq. (1.4): for the case p n, holds 2k−q 7q (i.e., the
term for computation time dominates), while it holds 2k−q 7q for the case p ≈ n (i.e., the term
for communication time dominates). Thus, we can conclude that our algorithm is not strongly scal-
able.
Now, we want to change our analysis a bit by not only increasing the number of PEs but additionally
increasing the input data size at the same time. This is known as weak scalability analysis. Fig. 1.5
shows the speedup and efficiency of our algorithm for n ranging from 1024 to 524,288 and p ranging
from 1 to 512. We can see that the efficiency is kept high (close to 100%) even for a large number of
PEs. This behavior can again be deduced from Eq. (1.4): since both n and p are scaled at the same
rate, the term relating to the computation time is constant for varying number of PEs (i.e. 2k−q = 1024
in Fig. 1.5), while the term for the communication time (7q = 7 × log(p)) only grows at a logarithmic
rate. Thus, we can conclude that our algorithm is weakly scalable.
The terms weak and strong scalability are also related to two well-known laws in parallel comput-
ing: Amdahl’s law and Gustafsson’s law, which we will discuss in more detail in Chapter 2.
Other documents randomly have
different content
“lightning expresses,” and to stop them at every little wayside station. The
engines were fed upon wood, and it was a common thing for trains to stop
their intolerable jolting for full twenty minutes to take fresh supplies of
wood and water.
There was immeasurably more of weariness then, in a journey from
Richmond or Cincinnati or Buffalo to New York, than would be tolerated
now in a trip across the continent. As a consequence few people travelled
except for short distances and a journey which we now think nothing of
making comfortably in a single night, was then a matter of grave
consequence, to be undertaken only after much deliberation and with much
of preparation. New York seemed more distant to the dweller in the West or
South than Hong Kong and Yokohama do in our time, and the number of
people who had journeyed beyond the borders of our own country was so
small that those who had done so were regarded as persons of interestingly
adventurous experience.
Quite necessarily all parts of the country were markedly provincial in
speech, manner, habits and even in dress. New England had a nasal dialect
of its own, so firmly rooted in use that it has required two or three
generations of exacting Yankee school marms to eradicate it from the
speech even of the educated class. New York state had another, and the
Southerner was known everywhere by a speech which “bewrayed” him.
And as it was with speech, so also was it with manners, customs, ideas.
Prejudice was everywhere rampant, opinion intolerant, and usage merciless
in its narrow illiberality. Only in what was then the West—the region
between the Alleghenies and the Mississippi—was there anything of
cosmopolitan liberality and tolerance. They were found in that region
because the population of the West had been drawn from all parts of the
country. Attrition of mind with mind, and the mingling of men of various
origin had there in a large degree worn off the angles of provincial prejudice
and bred a liberality of mind elsewhere uncommon in our country.
Edmonia and Dorothy were to make their formidable journey to New
York in easy stages. They remained for several days with friends in
Richmond, while completing those preliminary preparations which were
necessary before setting out for the national capital. They were to stay in
Washington for a fortnight, in Baltimore for three weeks, in Philadelphia for
a week or two, and in New York for nearly two months before sailing for
Europe in May.
The time was a very troubled one, on the subject of slavery. Not only
was it true that if the owner of a slave took the negro with him into any one
of the free states he by that act legally set him free, but it was also true that
the most devoted and loyal servant thus taken from the South into a
Northern state was subjected to every form of persuasive solicitation to
claim and assert his freedom. It was nevertheless the custom of Southern
men, and still more of Southern women, to take with them on their travels
one or more of their personal servants, trusting to their loyalty alone for
continued allegiance. For the attitude of such personal servants in Virginia
at that time was rather that of proud and voluntary allegiance to loved
masters and mistresses who belonged to them as a cherished possession,
than that of men and women held in unwilling bondage.
Accordingly it was arranged that Edmonia’s maid, Dinah—or Diana as
she had come to call herself since hearing her mistress read a “history
pome” aloud—should accompany the two young women as their joint
servitor.
As soon as this arrangement was announced at Branton, Diana began
what Polydore called “a puttin’ on of airs.” In plainer phrase she began to
snub Polydore mercilessly, whereas she had recently been so gracious in her
demeanor towards him as to give him what he called “extinct
discouragement.”
After it was settled that she was to accompany “Miss Mony an’ Miss
Dorothy” to “de Norf” and to “Yurrop”—as she wrote to all her friends who
were fortunate enough to know how to “read writin’,” there was, as
Polydore declared, “no livin’ in de house wid her.” She sailed about the
place like a frigate, delivering her shots to the right and left—most of them
aimed at Polydore, with casual and contemptuous attention, now and then,
to the other house servants.
“I ’clar’ to gracious,” said Elsie, one of the housemaids, “ef Diana ain’t a
puttin’ on of jes’ as many airs as ef she’d been all over a’ready, an’ she ain’t
never been out of dis county yit.”
“Wonder ef she’ll look at folks when she gits back,” said Fred, the cadet
of the dining room, who was being trained under Polydore’s tutelage to
keep his nails clean and to offer dishes to guests at their left hands.
“Don’ you be in too big a hurry to fin’ out dat, you nigga,” rejoined
Polydore, the loyalty of whose love for Diana would brook no criticism of
her on the part of an underling. “You’se got enough to attend to in gittin’ yer
manners into shape. Diana’s a superior pusson, an’ you ain’t got no ’casion
to criticise her. You jes’ take what yer gits an’ be thankful like Lazarus wuz
when de rich man dropped water outer his hand on his tongue.”
Polydore’s biblical erudition seems to have been a trifle at fault at this
point. But at any rate his simile had its intended effect upon the young
darkey, who, slipping a surreptitious beaten biscuit into his pocket, retreated
to the distant kitchen to devour it.
At that moment Diana entered the dining room with the air of a Duchess,
and, with unwonted sweetness, said:
“Please, Polydore, bring me de tea things. De ladies is faint.”
Polydore, anxious that Diana’s gentle mood should endure, made all
haste to bring what she desired. He made too much haste, unluckily, for in
his hurry he managed to spill a little hot water from a pitcher he was
carrying on a tray, and some drops of it fell upon the sleeve of Diana’s
daintily laundered cambric gown.
The stately bronze colored namesake of the ancient goddess rose in
offended dignity, and looked long at the offender before addressing him.
Then she witheringly put the question:
“Whar’s your manners dis mawnin’, Polydore? Jes’ spose I was Miss
Mony now; would you go sloppin’ things over her dat way?”
Even a worm will turn, we are told, and Polydore was prouder than a
worm. For once he lost his self-control so far as to say in reply:
“But you ain’t Miss Mony, dough you seems to think you is. I’se tired o’
yer highty tighty airs. Git de tea things for yerse’f!” With that Polydore left
the dining room, and Diana, curiously enough, made no reference to the
incident when next she encountered him, but was all smiles and sweetness
instead.
XXVIII
THE ADVANCING SHADOW
N O sooner were Dorothy and Edmonia gone than Arthur turned again to
affairs. It was a troubled uneasy time in Virginia, a time of sore
apprehension and dread. The “irrepressible conflict” over slavery had
that year taken on new and more threatening features than ever before.
There was now a strong political party at the North the one important
article of whose creed was hostility to the further extension of slavery into
the territories. It was a strictly sectional party in its composition, having no
existence anywhere at the South. It was influential in Congress, and in 1856
it had strongly supported a candidate of its own for president. By the
beginning of 1860 its strength had been greatly increased and circumstances
rendered probable its success in electing a president that year, for the
hopeless division of the Democratic party, which occurred later in the year,
was already clearly foreshadowed, an event which in fact resulted in the
nomination of three rival candidates against Mr. Lincoln and made his
election certain in spite of a heavy popular majority against him.
Had this been all, Virginia would not have been greatly disturbed by the
political situation and prospect. But during the preceding autumn the
Virginians had been filled with apprehension for the safety of their homes
and families by John Brown’s attempt, at Harper’s Ferry, to create a negro
insurrection, the one catastrophe always most dreaded by them. That raid,
quickly suppressed as it was, wrought a revolution in Virginian feeling and
sentiment. The Virginians argued from it, and from the approval given to it
in some parts of the North, that Northern sentiment was rapidly ripening
into readiness for any measures, however violent they might be, for the
extinction of slavery and the destruction of the autonomy of the Southern
States.
They found it difficult under the circumstances to believe the Republican
party’s disclaimer of all purpose or power to interfere with the institution in
the states. They were convinced that only opportunity was now wanting to
make the Southern States the victims of an aggressive war, with a servile
insurrection as a horrible feature of it. They cherished a warm loyalty to that
Union which Virginia had done so much to create, but they began seriously
to fear the time when there would be no peace or safety for their state or
even for their wives and children within the Union. They were filled with
resentment, too, of what they regarded as a wanton and unlawful purpose to
interfere with their private concerns, and to force the country into disunion
and civil war.
There were hot heads among them, of course, who were ready to
welcome such results; but these were very few. The great body of Virginia’s
people loved the Union, and even to the end—a year later—their strongest
efforts were put forth to persuade both sides to policies of peace.
But in the meantime a marked change came over the Virginian mind
with respect to slavery. Many who had always regarded the institution as an
inherited evil to be got rid of as soon as that might be safely accomplished,
modified or reversed their view when called upon to stand always upon the
defensive against what they deemed an unjust judgment of themselves.
Arthur Brent did not share this change of view, but he shared in the
feelings of resentment which had given it birth. In common with other
Virginians he felt that this was a matter belonging exclusively to the
individual states, and still more strongly he felt that the existing political
situation and the methods of it gravely menaced the Union in ways which
were exceedingly difficult for Southern men who loved the Union to meet.
He saw with regret the great change that was coming over public and
private sentiment in Virginia—sentiment which had been so strongly
favorable to the peaceable extinction of slavery, that John Letcher—a
lifelong advocate of emancipation as Virginia’s true policy—had been
elected Governor the year before upon that as the only issue of a state
campaign.
But Arthur was still bent upon carrying out his purpose of emancipating
himself and, incidentally his slaves. And the threatening aspect of political
affairs strengthened his determination at any rate to rid both his own estate
and Dorothy’s of debt.
“When that is done, we shall be safe, no matter what happens,” he told
himself.
To that end he had already done much. In spite of his preöccupation with
the fever epidemic he had found time during the autumn to institute many
economies in the management of both plantations. He had shipped and sold
the large surplus crops of apples and sweet potatoes—a thing wholly
unprecedented in that part of Virginia, where no products of the soil except
tobacco and wheat were ever turned to money account. He was laughed at
for what his neighbors characterized as “Yankee farming,” but both his
conscience and his bank account were comforted by the results. In the same
way, having a large surplus of corn that year, he had fattened nearly double
the usual number of hogs, and was now preparing to sell so much of the
bacon as he did not need for plantation uses. In these and other ways he
managed to diminish the Wyanoke debt by more than a third and that of
Pocahontas by nearly one-half, during his first year as a planter.
“If they don’t quit laughing at me,” he said to Archer Bannister one day,
“I’ll sell milk and butter and even eggs next summer. I may conclude to do
that anyhow. Those are undignified crops, perhaps, but I’m not sure that
they could not be made more profitable than wheat and tobacco.”
“Be careful, Arthur,” answered his friend. “It isn’t safe to make planting
too profitable. It is apt to lead to unkindly remark.”
“How so? Isn’t planting a business, like any other?”
“A business, yes, but not like any other. It has a certain dignity to
maintain. But I wasn’t thinking of that. I was thinking of Robert Copeland.”
“I wish you’d tell me about him, Archer. What has he done? I observe
that everybody seems to shun him—or at least nobody seems quite willing
to recognize him as a man in our class, though they tell me his family is
fairly good, and personally he seems agreeable. Nobody says anything to
his discredit, and yet I observe a general shoulder shrugging whenever his
name is mentioned.”
“He makes too many hogsheads of tobacco to the hand,” answered
Archer smiling but speaking with emphasis and slowly.
“Is he cruel to his negroes?”
“Yes, and no. He is always good natured with them and kindly in his
fashion, but he works them much too hard. He doesn’t drive them
particularly. Indeed I never heard of his striking one of them. But he has
invented a system of money rewards and the like, by which he keeps them
perpetually racing with each other in their work. They badly overtax
themselves, and the community regards the matter with marked disfavor. In
the matter of family he isn’t in our class at all, but his father was much
respected. He was even a magistrate for some years before his death. But
the son has shut himself out of all social position by over working his
negroes, and the fact that he does it in ways that are ingenious and not
brutal doesn’t alter the fact, at least not greatly. Of course, if he did it in
brutal ways he would be driven out of the county. As it is he is only shut out
of society. I was jesting when I warned you of danger of that sort. But if
you are not careful in your application of ‘practical’ methods down here,
you’ll get a reputation for money loving, and that wouldn’t be pleasant.”
Arthur stoutly maintained his right and his duty to market all that the two
plantations produced beyond their own needs, especially so long as there
were debts upon them. Till these should be discharged, he contended, he
had no moral right to let products go to waste which could be turned into
money. Archer admitted the justice of his view, but laughingly added:
“It isn’t our way, down here, and we are so conservative that it is never
quite prudent to transgress our traditions. At the same time I wish we could
all rid our estates from debt before the great trouble comes. For it is surely
coming and God only knows what the upshot of it all will be. Don’t quote
me as saying that, please. It isn’t fashionable with us to be pessimistic, or to
doubt either the righteousness or the ultimate triumph of our cause. But
nobody can really foresee the outcome of our present troubles, and
whatever it may be, the men who are out of debt when it comes—if there
are any—will be better equipped to meet fate with a calm mind than the rest
of us.”
XXIX
THE CORRESPONDENCE OF DOROTHY