Wrong values in local memory in OpenCL kernel using bariers - opencl

I have a simple kernel, which basically calculates the maximum from a list of doubles and stores its index. All work is done locally, with a work group size of 64.
In short, I create a list of indexes, populate it with consecutive numbers (based on local_id), and then move around based on fitness values.
Currently my main problem is the fact, that reading this list of indexes returns really crazy values. I have one printf statement and while it should print something like this
>> my_index 1 ; other_index 33 ; local_id 1 <<
>> my_index 2; other_index 34; local_id 2 <<
>> .......
The output I get is
>> my_index 1600085855 ; other_index 32 ; local_id 0 <<
>> my_index 1072652127 ; other_index 33 ; local_id 1 <<
>> my_index 942797699 ; other_index 34 ; local_id 2 <<
>> my_index 1072923423 ; other_index 35 ; local_id 3 <<
>> my_index -987348804 ; other_index 36 ; local_id 4 <<
>> my_index 1072849931 ; other_index 37 ; local_id 5 <<
>> my_index -833351863 ; other_index 38 ; local_id 6 <<
>> my_index 1073209710 ; other_index 39 ; local_id 7 <<
>> my_index -833351863 ; other_index 40 ; local_id 8 <<
>> my_index 1073209710 ; other_index 41 ; local_id 9 <<
>> my_index 1206451488 ; other_index 42 ; local_id 10 <<
>> my_index 1072822847 ; other_index 43 ; local_id 11 <<
>> my_index -1561806289 ; other_index 44 ; local_id 12 <<
>> my_index 1072836235 ; other_index 45 ; local_id 13 <<
>> my_index 1797893287 ; other_index 46 ; local_id 14 <<
>> my_index 1072863946 ; other_index 47 ; local_id 15 <<
>> my_index 1499829849 ; other_index 48 ; local_id 16 <<
>> my_index 1073309078 ; other_index 49 ; local_id 17 <<
>> my_index 1215556782 ; other_index 50 ; local_id 18 <<
>> my_index 1073623117 ; other_index 51 ; local_id 19 <<
>> my_index -1741202958 ; other_index 52 ; local_id 20 <<
>> my_index 1073061666 ; other_index 53 ; local_id 21 <<
>> my_index 1908874354 ; other_index 54 ; local_id 22 <<
>> my_index 1072809756 ; other_index 55 ; local_id 23 <<
>> my_index 1499829849 ; other_index 56 ; local_id 24 <<
>> my_index 1073309078 ; other_index 57 ; local_id 25 <<
>> my_index 1965493508 ; other_index 58 ; local_id 26 <<
>> my_index 1073421919 ; other_index 59 ; local_id 27 <<
>> my_index -1908874354 ; other_index 60 ; local_id 28 <<
>> my_index 1073101027 ; other_index 61 ; local_id 29 <<
>> my_index -1561806289 ; other_index 62 ; local_id 30 <<
>> my_index 31 ; other_index 63 ; local_id 31 <<
>> my_index 1600085855 ; other_index 1499829849 ; local_id 0 <<
>> my_index 1072652127 ; other_index 1073309078 ; local_id 1 <<
>> my_index 942797699 ; other_index 1215556782 ; local_id 2 <<
>> my_index 1072923423 ; other_index 1073623117 ; local_id 3 <<
>> my_index -987348804 ; other_index -1741202958 ; local_id 4 <<
>> my_index 1072849931 ; other_index 1073061666 ; local_id 5 <<
>> my_index -833351863 ; other_index 1908874354 ; local_id 6 <<
>> my_index 1073209710 ; other_index 1072809756 ; local_id 7 <<
>> my_index -833351863 ; other_index 1499829849 ; local_id 8 <<
>> my_index 1073209710 ; other_index 1073309078 ; local_id 9 <<
>> my_index 1206451488 ; other_index 1965493508 ; local_id 10 <<
>> my_index 1072822847 ; other_index 1073421919 ; local_id 11 <<
>> my_index -1561806289 ; other_index -1908874354 ; local_id 12 <<
>> my_index 1072836235 ; other_index 1073101027 ; local_id 13 <<
>> my_index 1797893287 ; other_index -1561806289 ; local_id 14 <<
>> my_index 1072863946 ; other_index 31 ; local_id 15 <<
>> my_index 1600085855 ; other_index -833351863 ; local_id 0 <<
>> my_index 1072652127 ; other_index 1073309078 ; local_id 1 <<
>> my_index 942797699 ; other_index 1965493508 ; local_id 2 <<
>> my_index 1073623117 ; other_index 1072822847 ; local_id 3 <<
>> my_index -1741202958 ; other_index -1908874354 ; local_id 4 <<
>> my_index 1072849931 ; other_index 1073101027 ; local_id 5 <<
>> my_index -833351863 ; other_index 1797893287 ; local_id 6 <<
>> my_index 1073209710 ; other_index 1072863946 ; local_id 7 <<
>> my_index -833351863 ; other_index -1908874354 ; local_id 0 <<
>> my_index 1073309078 ; other_index 1072849931 ; local_id 1 <<
>> my_index 942797699 ; other_index -833351863 ; local_id 2 <<
>> my_index 1073623117 ; other_index 1072863946 ; local_id 3 <<
>> my_index -833351863 ; other_index -833351863 ; local_id 0 <<
>> my_index 1073309078 ; other_index 1072863946 ; local_id 1 <<
>> my_index -833351863 ; other_index 1072863946 ; local_id 0 <<
How could it be?
Code:
__kernel void reduce( __global char* inputAgent,
__global double* output,
__global double* bestFitness,
__local double* localFitness,
__local int* indexes,
const unsigned int size)
{
int local_id = get_local_id(0);
// populate local memory
if (local_id <= size) {
localFitness[local_id] = bestFitness[local_id];
} else {
localFitness[local_id] = 0;
}
//populate table with consecutive numbers
indexes[local_id] = local_id;
barrier(CLK_LOCAL_MEM_FENCE);
for(int offset = get_local_size(0) / 2;
offset > 0;
offset >>= 1) {
if (local_id < offset) {
// find greater fitness
double mine = localFitness[local_id];
double other = localFitness[local_id + offset];
localFitness[local_id] = (mine > other) ? mine : other;
// store index of this greater fitness
int my_index = indexes[local_id];
int other_index = indexes[local_id + offset];
indexes[local_id] = (mine > other) ? my_index : other_index;
printf(">> my_index %d ; other_index %d ; local_id %d <<",
my_index, other_index, local_id);
}
barrier(CLK_LOCAL_MEM_FENCE);
}
if (local_id == 0) { //last, not mutated
// return
output[0] = localFitness[0];
// reuse found index
int bit_to_change = indexes[0];
if (bit_to_change < size) {
inputAgent[bit_to_change] = (inputAgent[bit_to_change] - 1) * -1;
}
}
}
Any suggestions welcome.
EDIT:
I was able to pinpoint problem to barrier. After adding to more printf's, one just before first barrier, and second just after:
[...]
indexes[localID] = localID;
printf("<<< Fit %f for %d\n", localFitness[localID], indexes[localID] );
barrier(CLK_LOCAL_MEM_FENCE);
printf("*** Fit %f for %d\n", localFitness[localID], indexes[localID] );
[...]
output I get :
<<< Fit 0.990099 for 0
<<< Fit 1.449275 for 1
<<< Fit 1.538462 for 2
<<< Fit 1.030928 for 3
[...]
******* Fit 0.990099 for -1636178018
******* Fit 1.449275 for 1072593383
******* Fit 1.538462 for -1184818564
******* Fit 1.030928 for 1072042407
******* Fit 2.222222 for -1688619621
******* Fit 2.222222 for 1072388533
[...]
which suggest that barrier doesn't work; and I don't know what to do with that. Any ideas?

I was able (with huge help form my colleague) to find the problem. There was a small issue in the bindings from Erlang to OpenCL. Later I will go in more detail on how I was able to find it (just to provide my debugging path), but for now I would like to just mark this question as solved.

Related

Subtracting columns based on greater than in bash

I have a file with multiple columns:
$ cat file.txt
a bc 34 67
t gh 68 -34
f jh -9 76
h in -66 -14
and so on
I am trying to extract when both columns are negative; when both are positive then subtract the two columns based on which value is greater; and if either column negative then add both the columns
For both negative its quite easy:
less file.txt | egrep -i "\-.*\-" | less
Expected Output:
h in -66 -14
For both positive I tried the following to no avail:
less file.txt | egrep -iv "\-.*\-" | awk '($3>$4 {print $0,($3-$4)}) || ($4>$3 {print $0,($4-$3)})' | less
Expected Output:
a bc 34 67 33
For either negative,
less file.txt | egrep -iv "\-.*\-" | awk '($3<0||$4<0) {print $0,($3+$4)}' | less
Expected Output:
t gh 68 -34 34
f jh -9 76 67
I am seeing this error:
awk: cmd. line:1: (FILENAME=- FNR=3208) fatal: print to "standard output" failed (Broken pipe)
egrep: write error
I know its a basic thing to do, any help would be appreciated!
One awk idea:
awk '
$3<0 && $4<0 { print $0 ; next }
$3>0 && $4>0 { print $0, ($3>=$4 ? $3-$4 : $4-$3); next }
{ print $0, $3+$4 }
' file.txt
NOTE: may need to be tweaked if $3==0 and/or $4==0 ... depends on OP's requirements for this scenario
This generates:
a bc 34 67 33
t gh 68 -34 34
f jh -9 76 67
h in -66 -14
Another awk implementation:
awk '
function abs(x) {
if (x < 0) x = -x
return x
}
$3 >= 0 || $4 >= 0 {$(NF+1) = abs(abs($3) - abs($4))}
{print}
' file.txt
a bc 34 67 33
t gh 68 -34 34
f jh -9 76 67
h in -66 -14
If you wanted to do this in plain bash:
abs() { echo $(($1 < 0 ? -($1) : $1)); }
while read -ra fields; do
a=${fields[2]}
b=${fields[3]}
if ((a >= 0 || b >= 0)); then
fields+=($(abs $(($(abs $a) - $(abs $b)))))
fi
echo "${fields[*]}"
done < file.txt

Count character in specific cell and add that character a specified amount of times

I am working on 16s data and try to format an OTU table to upload it to a different tool.
Here is my TSV table:
It is supposed to look like this:
So I need R to count the number of semicolons ";" in each cell in column "taxonomy" and if the number is smaller than 6 I need R to add the required number of semincolons to make it six semicolons per cell.
I am new to the bioinformatics field so any help would be much appreciated!
I tried
ifelse(str_count(ASV$taxonomy, ";") >= 6, ASV$taxonomy, paste0(ASV$taxonomy, " ;"))
But I donĀ“t know how I can tell R to add so many semicolons that it makes 6 semicolons in each cell.
Thank you in advance,
Lea
We could use separate with the fill argument from tidyr package and
then paste them all together and finally replace NA by ""
library(tidyverse)
df %>%
separate(col1, c("a","b","c","d","e","f","g"), fill = "right", sep = ";") %>%
mutate(col1 = paste(a,b,c,d,e,f,g, sep = "; "), .keep="unused") %>%
mutate(col1 = str_replace_all(col1, "NA", ""))
col1
<chr>
1 "Bacteria; Proteobacteria; Gammaproteobacteria; ; ; ; "
2 "Bacteria; Proteobacteria; Gammaproteobacteria; ; ; ; "
3 "Bacteria; Actinobacteria; Rubrobacteria; Rubrobacterales; Rubrobacteraceae; Rubrobacter; "
4 "Bacteria; Gemmatimonadetes; Gemm-1; ; ; ; "
5 "Bacteria; Proteobacteria; Gammaproteobacteria; Chromatiales; ; ; "
6 "Bacteria; Actinobacteria; Nitriliruptoria; Nitriliruptorales; Nitriliruptoraceae; ; "
7 "Bacteria; Proteobacteria; Gammaproteobacteria; Chromatiales; ; ; "
8 "Bacteria; Actinobacteria; Thermoleophilia; Solirubrobacterales; ; ; "
9 "Bacteria; Proteobacteria; Gammaproteobacteria; Chromatiales; ; ; "
10 "Bacteria; Proteobacteria; Alphaproteobacteria; Sphingomonadales; Sphingomonadaceae; Kaistobacter; "
11 "Bacteria; Actinobacteria; Thermoleophilia; Solirubrobacterales; ; ; "
12 "Bacteria; Proteobacteria; Betaproteobacteria; Burkholderiales; Oxalobacteraceae; Ralstonia; "
13 "Bacteria; Actinobacteria; Actinobacteria; Actinomycetales; Pseudonocardiaceae; ; "
14 "Bacteria; Actinobacteria; Actinobacteria; Actinomycetales; Micrococcaceae; Arthrobacter; "
data:
structure(list(col1 = c("Bacteria; Proteobacteria; Gammaproteobacteria;",
"Bacteria; Proteobacteria; Gammaproteobacteria;", "Bacteria; Actinobacteria; Rubrobacteria; Rubrobacterales; Rubrobacteraceae; Rubrobacter;",
"Bacteria; Gemmatimonadetes; Gemm-1;", "Bacteria; Proteobacteria; Gammaproteobacteria; Chromatiales;",
"Bacteria; Actinobacteria; Nitriliruptoria; Nitriliruptorales; Nitriliruptoraceae;",
"Bacteria; Proteobacteria; Gammaproteobacteria; Chromatiales;",
"Bacteria; Actinobacteria; Thermoleophilia; Solirubrobacterales;",
"Bacteria; Proteobacteria; Gammaproteobacteria; Chromatiales;",
"Bacteria; Proteobacteria; Alphaproteobacteria; Sphingomonadales; Sphingomonadaceae; Kaistobacter;",
"Bacteria; Actinobacteria; Thermoleophilia; Solirubrobacterales;",
"Bacteria; Proteobacteria; Betaproteobacteria; Burkholderiales; Oxalobacteraceae; Ralstonia;",
"Bacteria; Actinobacteria; Actinobacteria; Actinomycetales; Pseudonocardiaceae;",
"Bacteria; Actinobacteria; Actinobacteria; Actinomycetales; Micrococcaceae; Arthrobacter;"
)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA,
-14L))
Since I don't have your dataset, I just made an example dataframe.
Next time when you ask, make sure you don't post image of codes/dataset, you should use dput(your_data) and paste the result in the question.
Input
library(tidyverse)
library(stringr)
df <- tibble(Name = LETTERS[1:4],
OTU = c("A;", "A; B;", "A; B; C; D; E; F;", "A; B; C; D; E;"))
df
# A tibble: 4 x 2
Name OTU
<chr> <chr>
1 A A;
2 B A; B;
3 C A; B; C; D; E; F;
4 D A; B; C; D; E;
Code and output
First count the number of ";" in the column, if it's fewer than 6, add some more at the end of the string in OTU. If it is not fewer than 6, use the original OTU value.
This will entirely replace the original OTU column.
df %>% mutate(OTU = ifelse(str_count(OTU, ";") < 6,
paste(OTU, str_dup("; ", 6 - str_count(OTU, ";"))),
OTU))
# A tibble: 4 x 2
Name OTU
<chr> <chr>
1 A "A; ; ; ; ; ; "
2 B "A; B; ; ; ; ; "
3 C "A; B; C; D; E; F;"
4 D "A; B; C; D; E; ; "

How to switch between radians and degrees in SAS

just looking for an easy way to run trig functions in SAS without having to manually correct in each calculation. Below is what I am working with.
I am running this in SAS 9 probably, the SAS Studio Student Module but this is a general SAS question.
I have manually created a variable, 'rad' in the 'calc' data step to deal with this but it adds a step of complexity that I would like to avoid.
I am asking whether there is a system setting, alternate trig function or ... ? that would change the calculation from:
bh_x = cos(rad*bh_a)*bh_l ;
to:
bh_x = cos(bh_a)*bh_l ;
so I don't have to manually convert my angle in degrees to radians for the trig function to work.
Thanks to anyone reading this and putting any mental effort to the solution!
Tim
data spec ;
length
b2h_a 8
b2h_l 8
b2h_l_e 8
bike $ 8
name $ 16
;
input
bike $
name $
bh_a
bh_l
ht_a
spcr
st_h
st_a
st_l
hb_r
hb_a
;
datalines ;
srcn (0,0) 0 0 67 0 0 0 0 0 0
srcn c 41 658 71.5 27 40 25 120 100 13
srcn ne_27_n13 41 658 71.5 27 40 27 127 100 13
srcn ne_15_0 41 658 71.5 15 40 27 127 100 0
srcn ne_5_0 41 658 71.5 5 40 27 127 100 0
srcn ne_2_n9 41 658 71.5 2 40 27 127 100 9
srcn ne_5_10 41 658 71.5 5 40 27 127 100 -10
srcn ne_10_rf10 41 658 71.5 10 40 27 127 20 -10
srcn max 41 658 90 250 0 0 250 0 0
;
run ;
data calc ;
set spec ;
pi=constant('pi') ;
rad=pi/180 ;
bh_x = cos(rad*bh_a)*bh_l ;
bh_y = sin(rad*bh_a)*bh_l ;
sr_x = (cos(rad*ht_a)*(spcr+st_h/2))*-1 ;
sr_y = sin(rad*ht_a)*(spcr+st_h/2);
st_x = cos(rad*(90-ht_a+st_a))*st_l ;
st_y = sin(rad*(90-ht_a+st_a))*st_l ;
hb_x = cos(rad*(90-hb_a))*hb_r*-1 ;
hb_y = sin(rad*(90-hb_a))*hb_r ;
hd_x = bh_x + sr_x + st_x + hb_x ;
hd_y = bh_y + sr_y + st_y + hb_y ;
if hd_x=0 then do ;
b2h_a=0 ;
b2h_l=0 ;
end ;
else do ;
b2h_a = atan(hd_y/hd_x)/rad ;
b2h_l = hd_y/sin(b2h_a*rad) ;
end ;
b2h_l_e = b2h_l/25.4 ;
drop pi rad ;
format
b2h_a 5.
b2h_l 5.
b2h_l_e 5.
bh_a 5.
bh_l 5.
ht_a 5.
spcr 5.
st_h 5.
st_a 5.
st_l 5.
hb_r 5.
hb_a 5.
bh_x 5.
bh_y 5.
sr_x 5.
sr_y 5.
st_x 5.
st_y 5.
hb_x 5.
hb_y 5.
hd_x 5.
hd_y 5.
b2h_a 5.
b2h_l 5.
b2h_l_e 5.1
;
run ;
There are no trig functions in SAS that accept DEGREE or GRADIAN arguments. You always need to convert from your data's angular measurement system to RADIAN.
You can write a macro to perform the conversion. Example:
%macro cosD(theta);
%* theta is angle in degrees;
%* emit data step source code that performs conversion from degrees to radians;
cos(&theta*constant('PI')/180)
%mend;
In use:
data calc ;
set spec ;
bh_x = %cosD(bh_a) * bh_l ;
You could convert the angular data to radians during the step where input occurs and then not have to worry about it again.

Does GDB support displaying contents as pointer typed values?

Windbg has a dpp command, which interprets values in memory as pointers and prints out the pointer is pointing to. Shown below:
My questions is, does GDB has similar functionality?
On the gdb command line you can cast addresses to pointer values.
(gdb) list
1 #include <stdio.h>
2
3 char * m = "this is a test\n";
4
5 main()
6 {
7 printf("%s",m);
8 }
(gdb) b 7
Breakpoint 1 at 0x400531: file example.c, line 7.
(gdb) r
Starting program: /tmp/example
Breakpoint 1, main () at example.c:7
7 printf("%s",m);
(gdb) p m
$1 = 0x4005d4 "this is a test\n"
(gdb) p *(char*)0x4005d4
$2 = 116 't'
(gdb) p *(int*)0x4005d4
$3 = 1936287860
(gdb) p *(double**)0x4005d4
$5 = (double *) 0x2073692073696874
The last two are rubbish of course since the value is a char *.
The dump command is also useful for looking at hex value.
(gdb) x/20c m
0x4005d4: 116 't' 104 'h' 105 'i' 115 's' 32 ' ' 105 'i' 115 's' 32 ' '
0x4005dc: 97 'a' 32 ' ' 116 't' 101 'e' 115 's' 116 't' 10 '\n' 0 '\000'
0x4005e4: 37 '%' 115 's' 0 '\000' 0 '\000'

Awk - Create a matching key- Take $4$3$2 from Line 01 and $4 from Line 07

Desired Matching Key:
$4$3$2 from line 01 and $4 from line 07 of File1.txt
Example: In File1.txt $4=5000, $3=68, $2=89 in line 01 and $4=RT0429 or RT0428 or RT0588 in line 07.
The matching key in File2.txt is 50006889RT0428
Issue:
I am looking to create a match key from File1.txt and match against File2.txt first 14 characters.
File1.txt (input)
01 89 68 5000
02 83 11
04 83 9 02
03 83 00
06 83 00
07 83 11 RT0429
07 83 09 RT0428
07 88 10 RT0588
01 44 73 8800
02 44 73
04 44 73 02
03 44 73
06 44 73
07 44 11 RT0789
File2.txt (input)
50006889RT0428 CCARD /3010 /E /C A87545457 / // ///11 ///
51002387 CCARD /3000 /E /S N054896334IV / // ///11 ///
51002390800666 CCARD /3000 /E /S N0978898IV / // ///11 ///
File3 (Desired Output)
Since only the first record from File1.txt has the matching key, the output would have the matching record from File2.txt
50006889RT0428 CCARD /3010 /E /C A87545457 / // ///11 ///
Script I am using
awk '
BEGIN {
OFS="\t"
out = "File3.txt"
err = "File4.txt"
}
NR==FNR && NF {line[$1]=$0; next}
function print_77_99() {
if (key in line)
print "77", line[key] > out
else {
print "99", date > out
printf "%s", lines >> err
}
}
$1 == "01" {
if (FNR > 1) print_77_99()
key = $4 $3 $2
lines = ""
}
{
print > out
lines = lines $0 "\n"
}
END {print_77_99()}
' File2.txt File1.txt
As per reading my comment it sounds unclear to me, here what I think would do:
(Code adapted from Jonathan leffler's answer in this question
FNR == NR && ! /^[[:space:]]*$/ {
key = substr($1, 1, 8)
a[key] = $0
next
}
$1 == "01" { if (code != 0)
{
if (code in a)
{
print a[code]
delete a[code]
}
}
code = $4$3$2
}
END {
if (code in a)
{
print a[code]
delete a[code]
}
}

Resources