char Version[] = "wiggle 0.9 2012-05-14 GPL-2+ http://neil.brown.name/wiggle/\n";
-char short_options[] = "xdmwlrhiW123p::VRvqB";
+char short_options[] = "xdmwlrhiW123p::VRvqBb";
struct option long_options[] = {
{"browse", 0, 0, 'B'},
{"strip", 1, 0, 'p'},
{"no-ignore", 0, 0, 'i'},
{"show-wiggle", 0, 0, 'W'},
+ {"ignore-blanks",0,0, 'b'},
{"self-test", 0, 0, SELF_TEST},
{0, 0, 0, 0}
};
find . -name core | xargs rm -f
list=$(find . -type f \( -name script -o -name diff -o -name ldiff \
-o -name rediff -o -name merge -o -name wmerge -o -name lmerge \
- -o -name replace -o -name Wmerge \)
+ -o -name replace -o -name Wmerge -o -name bmerge \)
)
for path in $list
do
else $TIME $WIGGLE -mW orig new new2 | diff -u Wmerge - ; xit=$?
fi
;;
+ bmerge ) if [ -f patch ]
+ then $TIME $WIGGLE -mbw orig patch | diff -u bmerge - ; xit=$?
+ else $TIME $WIGGLE -mbw orig new new2 | diff -u bmerge - ; xit=$?
+ fi
+ ;;
esac
if [ $xit = 0 ]; then msg=SUCCEEDED; else msg=FAILED; fi
if grep 'ERROR SUMMARY: [1-9]' $vallog > /dev/null 2>&1
while (start < end) {
char *cp = start;
+ char *cp2;
+ int prefix = 0;
+
+ if (type == (ByWord | IgnoreBlanks))
+ while (cp < end &&
+ (*cp == ' ' || *cp == '\t')) {
+ prefix++;
+ cp++;
+ }
+ start = cp;
if (*cp == '\0' && cp+19 < end && cp[18] == '\n') {
/* special word */
cp += 20;
} else
- switch (type) {
+ switch (type & ByMask) {
case ByLine:
while (cp < end && *cp != '\n')
cp++;
cp++;
break;
}
+ cp2 = cp;
+ if (type == (ByWord | IgnoreBlanks) &&
+ *start && *start != '\n')
+ while (cp2 < end &&
+ (*cp2 == ' ' || *cp2 == '\t' || *cp2 == '\n')) {
+ cp2++;
+ if (cp2[-1] == '\n')
+ break;
+ }
if (list) {
list->start = start;
list->len = cp-start;
- list->plen = list->len;
- list->prefix = 0;
+ list->plen = cp2-start;
+ list->prefix = prefix;
if (*start)
list->hash = hash(start, list->len, 0);
else
list++;
}
cnt++;
- start = cp;
+ start = cp2;
}
return cnt;
}
--- /dev/null
+\begin{ abstract }
+ % Start with a two-sentence (at most) description of the big-picture
+ % problem and why we care, and a sentence at the end that emphasizes how
+ % your work is part of the solution.
+
+ Heterogeneous systems with <<<---Central Processing Units |||CPUs ===central CPUs --->>>and accelerators such as GPUs, FPGAs or the upcoming Intel MIC are becoming
+ mainstream. In these systems, peak performance includes the performance
+ of not just the CPUs but also all available accelerators. In spite of this
+ fact, the majority of programming models for heterogeneous computing focus
+ on only one of these. With the development of Accelerated OpenMP for GPUs,
+ both from PGI and Cray, we have a clear path to extend traditional OpenMP
+ applications incrementally to use GPUs. The extensions are geared toward
+ switching from CPU parallelism to GPU parallelism. However they do not
+ preserve the former while adding the latter. Thus computational potential is
+ wasted since either the CPU cores or the GPU cores are left idle. Our goal
+ is to create a runtime system that can intelligently divide an accelerated
+ OpenMP region across all available resources automatically. This paper
+ presents our proof-of-concept runtime system for dynamic task scheduling
+ across CPUs and GPUs. Further, we motivate the addition of this system into
+ the proposed \emph{OpenMP for Accelerators} standard. Finally, we show that
+ this option can produce as much as a two-fold performance improvement over
+ using either the CPU or GPU alone.
+
+\end{ abstract }
--- /dev/null
+\begin{abstract}
+ % Start with a two-sentence (at most) description of the big-picture
+ % problem and why we care, and a sentence at the end that emphasizes how
+ % your work is part of the solution.
+
+ Heterogeneous systems with CPUs and computational accelerators such as GPUs, FPGAs or
+ the upcoming Intel MIC are becoming mainstream. In these systems, peak performance
+ includes the performance of not just the CPUs but also all available accelerators. In
+ spite of this fact, the majority of programming models for heterogeneous computing
+ focus on only one of these. With the development of Accelerated OpenMP for GPUs, both
+ from PGI and Cray, we have a clear path to extend traditional OpenMP applications
+ incrementally to use GPUs. The extensions are geared toward switching from CPU
+ parallelism to GPU parallelism. However they do not preserve the former while adding
+ the latter. Thus computational potential is wasted since either the CPU cores or the
+ GPU cores are left idle. Our goal is to create a runtime system that can
+ intelligently divide an accelerated OpenMP region across all available resources
+ automatically. This paper presents our proof-of-concept runtime system for dynamic
+ task scheduling across CPUs and GPUs. Further, we motivate the addition of this
+ system into the proposed \emph{OpenMP for Accelerators} standard. Finally, we show
+ that this option can produce as much as a two-fold performance improvement over using
+ either the CPU or GPU alone.
+
+\end{abstract}
--- /dev/null
+\begin {abstract}
+ % Start with a two-sentence (at most) description of the big-picture
+ % problem and why we care, and a sentence at the end that emphasizes how
+ % your work is part of the solution.
+
+ Heterogeneous systems with central CPUs and accelerators such as
+ GPUs, FPGAs or the upcoming Intel MIC are becoming mainstream.
+ In these systems, peak performance includes the performance of not
+ just the CPUs but also all available accelerators. In spite of
+ this fact, the majority of programming models for heterogeneous
+ computing focus on only one of these. With the development of
+ Accelerated OpenMP for GPUs, both from PGI and Cray, we have a
+ clear path to extend traditional OpenMP applications incrementally
+ to use GPUs. The extensions are geared toward switching from CPU
+ parallelism to GPU parallelism. However they do not preserve the
+ former while adding the latter. Thus computational potential is
+ wasted since either the CPU cores or the GPU cores are left idle.
+ Our goal is to create a runtime system that can intelligently
+ divide an accelerated OpenMP region across all available resources
+ automatically. This paper presents our proof-of-concept runtime
+ system for dynamic task scheduling across CPUs and GPUs. Further,
+ we motivate the addition of this system into the proposed
+ \emph{OpenMP for Accelerators} standard. Finally, we show that
+ this option can produce as much as a two-fold performance
+ improvement over using either the CPU or GPU alone.
+
+\end{abstract}
--- /dev/null
+\begin{ abstract }
+ % Start with a two-sentence (at most) description of the big-picture
+ % problem and why we care, and a sentence at the end that emphasizes how
+ % your work is part of the solution.
+
+ Heterogeneous systems with Central Processing Units and computational
+ accelerators such as GPUs, FPGAs or the upcoming Intel MIC are becoming
+ mainstream. In these systems, peak performance includes the performance
+ of not just the CPUs but also all available accelerators. In spite of this
+ fact, the majority of programming models for heterogeneous computing focus
+ on only one of these. With the development of Accelerated OpenMP for GPUs,
+ both from PGI and Cray, we have a clear path to extend traditional OpenMP
+ applications incrementally to use GPUs. The extensions are geared toward
+ switching from CPU parallelism to GPU parallelism. However they do not
+ preserve the former while adding the latter. Thus computational potential is
+ wasted since either the CPU cores or the GPU cores are left idle. Our goal
+ is to create a runtime system that can intelligently divide an accelerated
+ OpenMP region across all available resources automatically. This paper
+ presents our proof-of-concept runtime system for dynamic task scheduling
+ across CPUs and GPUs. Further, we motivate the addition of this system into
+ the proposed \emph{OpenMP for Accelerators} standard. Finally, we show that
+ this option can produce as much as a two-fold performance improvement over
+ using either the CPU or GPU alone.
+
+\end{ abstract }
};
static int merge_window(struct plist *p, FILE *f, int reverse, int replace,
- int selftest)
+ int selftest, int ignore_blanks)
{
/* Display the merge window in one of the selectable modes,
* starting with the 'merge' mode.
return 0;
}
/* FIXME check for errors in the stream */
- fm = split_stream(sm, ByWord);
- fb = split_stream(sb, ByWord);
- fa = split_stream(sa, ByWord);
+ fm = split_stream(sm, ByWord | ignore_blanks);
+ fb = split_stream(sb, ByWord | ignore_blanks);
+ fa = split_stream(sa, ByWord | ignore_blanks);
if (ch)
csl1 = pdiff(fm, fb, ch);
static int show_merge(char *origname, FILE *patch, int reverse,
int is_merge, char *before, char *after,
- int replace, int selftest)
+ int replace, int selftest, int ignore_blanks)
{
struct plist p;
p.after = after;
freopen("/dev/null","w",stderr);
- return merge_window(&p, patch, reverse, replace, selftest);
+ return merge_window(&p, patch, reverse, replace, selftest,
+ ignore_blanks);
}
-static void calc_one(struct plist *pl, FILE *f, int reverse)
+static void calc_one(struct plist *pl, FILE *f, int reverse,
+ int ignore_blanks)
{
struct stream s1, s2;
struct stream s = load_segment(f, pl->start, pl->end);
struct file ff, fp1, fp2;
struct csl *csl1, *csl2;
struct ci ci;
- ff = split_stream(sf, ByWord);
- fp1 = split_stream(s1, ByWord);
- fp2 = split_stream(s2, ByWord);
+ ff = split_stream(sf, ByWord | ignore_blanks);
+ fp1 = split_stream(s1, ByWord | ignore_blanks);
+ fp2 = split_stream(s2, ByWord | ignore_blanks);
if (pl->chunks)
csl1 = pdiff(ff, fp1, pl->chunks);
else
}
static int get_next(int pos, struct plist *pl, int n, int mode,
- FILE *f, int reverse)
+ FILE *f, int reverse, int ignore_blanks)
{
int found = 0;
if (pos == -1)
if (pos < 0)
return -1;
if (pl[pos].calced == 0 && pl[pos].end)
- calc_one(pl+pos, f, reverse);
+ calc_one(pl+pos, f, reverse, ignore_blanks);
if (pl[pos].last >= 0)
/* always see directories */
found = 1;
return pos;
}
-static void draw_one(int row, struct plist *pl, FILE *f, int reverse)
+static void draw_one(int row, struct plist *pl, FILE *f, int reverse,
+ int ignore_blanks)
{
char hdr[12];
hdr[0] = 0;
}
if (pl->calced == 0 && pl->end)
/* better load the patch and count the chunks */
- calc_one(pl, f, reverse);
+ calc_one(pl, f, reverse, ignore_blanks);
if (pl->end == 0) {
strcpy(hdr, " ");
} else {
clrtoeol();
}
-static int save_one(FILE *f, struct plist *pl, int reverse)
+static int save_one(FILE *f, struct plist *pl, int reverse,
+ int ignore_blanks)
{
struct stream sp, sa, sb, sm;
struct file fa, fb, fm;
chunks = split_patch(sp, &sa, &sb);
else
chunks = split_patch(sp, &sb, &sa);
- fb = split_stream(sb, ByWord);
- fa = split_stream(sa, ByWord);
+ fb = split_stream(sb, ByWord | ignore_blanks);
+ fa = split_stream(sa, ByWord | ignore_blanks);
sm = load_file(pl->file);
- fm = split_stream(sm, ByWord);
+ fm = split_stream(sm, ByWord | ignore_blanks);
csl1 = pdiff(fm, fb, chunks);
csl2 = diff_patch(fb, fa);
ci = make_merger(fm, fb, fa, csl1, csl2, 0, 1, 0);
NULL
};
static void main_window(struct plist *pl, int *np, FILE *f, int reverse,
- int replace)
+ int replace, int ignore_blanks)
{
/* The main window lists all files together with summary information:
* number of chunks, number of wiggles, number of conflicts.
/* Ok, row and pos could be trustworthy now */
tpos = pos;
for (i = row; i >= 1; i--) {
- draw_one(i, &pl[tpos], f, reverse);
+ draw_one(i, &pl[tpos], f, reverse, ignore_blanks);
tpos = get_prev(tpos, pl, *np, mode);
}
tpos = pos;
for (i = row+1; i < rows; i++) {
- tpos = get_next(tpos, pl, *np, mode, f, reverse);
+ tpos = get_next(tpos, pl, *np, mode, f, reverse,ignore_blanks);
if (tpos >= 0)
- draw_one(i, &pl[tpos], f, reverse);
+ draw_one(i, &pl[tpos], f, reverse, ignore_blanks);
else
- draw_one(i, NULL, f, reverse);
+ draw_one(i, NULL, f, reverse, ignore_blanks);
}
}
attrset(0);
case 'N':
case 'N'-64:
case KEY_DOWN:
- tpos = get_next(pos, pl, *np, mode, f, reverse);
+ tpos = get_next(pos, pl, *np, mode, f, reverse, ignore_blanks);
if (tpos >= 0) {
pos = tpos;
row++;
if (getmouse(&mevent) != OK)
break;
while (row < mevent.y &&
- (tpos = get_next(pos, pl, *np, mode, f, reverse))
+ (tpos = get_next(pos, pl, *np, mode, f, reverse, ignore_blanks))
>= 0) {
pos = tpos;
row++;
} else {
int c;
if (pl[pos].is_merge)
- c = merge_window(&pl[pos], NULL, reverse, 0, 0);
+ c = merge_window(&pl[pos], NULL, reverse, 0, 0, ignore_blanks);
else
- c = merge_window(&pl[pos], f, reverse, 0, 0);
+ c = merge_window(&pl[pos], f, reverse, 0, 0, ignore_blanks);
refresh = 2;
if (c) {
pl[pos].is_merge = 1;
if (pl[i].end
&& !pl[i].is_merge)
save_one(f, &pl[i],
- reverse);
+ reverse,
+ ignore_blanks);
}
} else
cnt = 0;
/* Already saved */
mesg = "File is already saved.";
} else {
- if (save_one(f, &pl[pos], reverse) == 0) {
+ if (save_one(f, &pl[pos], reverse, ignore_blanks) == 0) {
pl[pos].is_merge = 1;
snprintf(mesg_buf, cols,
"Saved file %s.",
mesg = "File has been restored.";
pl[pos].is_merge = 0;
refresh = 1;
- calc_one(&pl[pos], f, reverse);
+ calc_one(&pl[pos], f, reverse, ignore_blanks);
} else
mesg = "Could not restore file!";
}
}
int vpatch(int argc, char *argv[], int patch, int strip,
- int reverse, int replace, int selftest)
+ int reverse, int replace, int selftest, int ignore_blanks)
{
/* NOTE argv[0] is first arg...
* Behaviour depends on number of args:
fprintf(stderr, "%s: aborting\n", Cmd);
exit(2);
}
- main_window(pl, &num_patches, in, reverse, replace);
+ main_window(pl, &num_patches, in, reverse, replace, ignore_blanks);
plist_free(pl, num_patches);
fclose(in);
break;
fprintf(stderr, "%s: aborting\n", Cmd);
exit(2);
}
- main_window(pl, &num_patches, f, reverse, replace);
+ main_window(pl, &num_patches, f, reverse, replace,ignore_blanks);
plist_free(pl, num_patches);
} else if (strlen(argv[0]) > 4 &&
strcmp(argv[0]+strlen(argv[0])-4, ".rej") == 0) {
char *origname = strdup(argv[0]);
origname[strlen(origname) - 4] = '\0';
show_merge(origname, f, reverse, 0, NULL, NULL,
- replace, selftest);
+ replace, selftest, ignore_blanks);
} else
show_merge(argv[0], f, reverse, 1, NULL, NULL,
- replace, selftest);
+ replace, selftest, ignore_blanks);
break;
case 2: /* an orig and a diff/.ref */
exit(1);
}
show_merge(argv[0], f, reverse, 0, NULL, NULL,
- replace, selftest);
+ replace, selftest, ignore_blanks);
break;
case 3: /* orig, before, after */
show_merge(argv[0], NULL, reverse, 0, argv[1], argv[2],
- replace, selftest);
+ replace, selftest, ignore_blanks);
break;
}
be wiggled in to place.
.TP
-.BR -w ", " \-\-words
+.BR \-w ", " \-\-words
Request that all operations and display be word based. This is the
default for the "diff" function.
.TP
-.BR -l ", " \-\-lines
+.BR \-l ", " \-\-lines
Request that all operations and display be line based.
+.TP
+.BR \-b ", " \-\-ignore\-blanks
+De-emphasise white space (space, tab, and newline) is determining
+differences and changes.
+
+Normally white space is treated like a word which can be matched or
+changed by a patch. When this flag is in force, white space serves
+only as a separator between other words and is not matched itself.
+The effect of this is that changes in the amount of white space are
+not treated as significant.
+
+To be precise, any white space is combined with the preceeding word
+or, in the case of leading space on a line, with the following word.
+However it is not involved in any comparisons of that word. If a patch
+deletes a word, the attached white space is deleted as well. If a
+patch adds a word, the attached white space is added as well.
+
+An empty line, or one that contains only blanks, will be treated as a
+single word that will match any other blank line, no matter how many
+spaces it has.
+
+.B \-b
+has no effect in
+.B \-\-line
+mode.
+
.TP
.BR -p ", " \-\-patch
Treat the last named file as a patch instead of a file (with \-\-diff)
flist[1] = flist[2];
flist[2] = f;
}
- fl[0] = split_stream(flist[0], obj == 'l' ? ByLine : ByWord);
- fl[1] = split_stream(flist[1], obj == 'l' ? ByLine : ByWord);
+ fl[0] = split_stream(flist[0], obj);
+ fl[1] = split_stream(flist[1], obj);
if (chunks2 && !chunks1)
csl = pdiff(fl[0], fl[1], chunks2);
else
csl = diff_patch(fl[0], fl[1]);
- if (obj == 'l') {
+ if ((obj & ByMask) == ByLine) {
if (!chunks1)
printf("@@ -1,%d +1,%d @@\n",
fl[0].elcnt, fl[1].elcnt);
return exit_status;
}
-static int do_merge(int argc, char *argv[], int obj,
+static int do_merge(int argc, char *argv[], int obj, int blanks,
int reverse, int replace, int ignore, int show_wiggles,
int quiet)
{
outfile = fdopen(fd, "w");
}
- if (obj == 'l') {
- fl[0] = split_stream(flist[0], ByLine);
- fl[1] = split_stream(flist[1], ByLine);
- fl[2] = split_stream(flist[2], ByLine);
- } else {
- fl[0] = split_stream(flist[0], ByWord);
- fl[1] = split_stream(flist[1], ByWord);
- fl[2] = split_stream(flist[2], ByWord);
- }
+ if (obj == 'l')
+ blanks |= ByLine;
+ else
+ blanks |= ByWord;
+ fl[0] = split_stream(flist[0], blanks);
+ fl[1] = split_stream(flist[1], blanks);
+ fl[2] = split_stream(flist[2], blanks);
+
if (chunks2 && !chunks1)
csl1 = pdiff(fl[0], fl[1], chunks2);
else
return (ci.conflicts > 0);
}
-static int multi_merge(int argc, char *argv[], int obj,
+static int multi_merge(int argc, char *argv[], int obj, int blanks,
int reverse, int ignore, int show_wiggles,
int replace, int strip,
int quiet)
pl[i].start, pl[i].end, filename);
av[0] = pl[i].file;
av[1] = name;
- rv |= do_merge(2, av, obj, reverse, 1, ignore,
+ rv |= do_merge(2, av, obj, blanks, reverse, 1, ignore,
show_wiggles, quiet);
}
return rv;
char *helpmsg;
char *trace;
int selftest = 0;
+ int ignore_blanks = 0;
trace = getenv("WIGGLE_TRACE");
if (trace && *trace)
reverse = 1;
continue;
+ case 'b':
+ ignore_blanks = IgnoreBlanks;
+ continue;
+
case 'i':
ignore = 0;
continue;
if (mode == 'B') {
vpatch(argc-optind, argv+optind, ispatch,
- strip, reverse, replace, selftest);
+ strip, reverse, replace, selftest,
+ ignore_blanks);
/* should not return */
exit(1);
}
exit_status = extract(argc-optind, argv+optind, ispatch, which);
break;
case 'd':
- exit_status = do_diff(argc-optind, argv+optind, obj, ispatch, which, reverse);
+ exit_status = do_diff(argc-optind, argv+optind,
+ (obj == 'l' ? ByLine : ByWord)
+ | ignore_blanks,
+ ispatch, which, reverse);
break;
case 'm':
if (ispatch)
exit_status = multi_merge(argc-optind,
argv+optind, obj,
+ ignore_blanks,
reverse, ignore,
show_wiggles,
replace, strip,
quiet);
else
- exit_status = do_merge(argc-optind, argv+optind, obj, reverse, replace,
- ignore, show_wiggles, quiet);
+ exit_status = do_merge(
+ argc-optind, argv+optind,
+ obj, ignore_blanks, reverse, replace,
+ ignore, show_wiggles, quiet);
break;
}
exit(exit_status);
extern int do_trace;
extern int vpatch(int argc, char *argv[], int patch, int strip,
- int reverse, int replace, int selftest);
+ int reverse, int replace, int selftest,
+ int ignore_blanks);
extern char *Cmd;
extern char Version[];
extern void cleanlist(struct file a, struct file b, struct csl *list);
enum {
- ByLine,
- ByWord,
+ ByLine = 0,
+ ByWord = 1,
+ ByMask = 3,
+ IgnoreBlanks = 8, /* 'or'ed in */
};