Reputation: 33
I write a shell script to auto generate a kernel code:
#!/bin/bash
# -----------------------------------------------------------
# Description: Register Blocking CSR kernel auto generation.
# -----------------------------------------------------------
#set -x
KERNEL_SRC=kernel.cpp
file_gen() {
if [ -f ${KERNEL_SRC} ]
then
rm -f ${KERNEL_SRC}
touch ${KERNEL_SRC}
fi
echo "/*">>${KERNEL_SRC}
echo " * Register Blocking CSR implement.">>${KERNEL_SRC}
echo " *">>${KERNEL_SRC}
echo " */">>${KERNEL_SRC}
echo >>${KERNEL_SRC}
echo >>${KERNEL_SRC}
}
emit_func_header() {
R=$1
C=$2
echo "void bcsr_${R}x${C}(const int &bm, const int *b_row_start, const int *b_col_idx," >> ${KERNEL_SRC}
echo "const double *b_values, const double *x, double *y) {" >> ${KERNEL_SRC}
}
emit_func_body() {
local R=${1}
local C=${2}
#echo ${R} ${C}
echo "int i, j;" >>${KERNEL_SRC}
echo "double" >>${KERNEL_SRC}
local m=$(( ${R} - 1 ))
# emit d0, d1, ..., d(r-1), x0, x1, ..., x(c-1)
for i in `seq 0 $m`
do
echo "d${i}, ">>${KERNEL_SRC}
done
local t=$(( ${C} - 1 ))
for i in `seq 0 $t`
do
if [ ${i} -eq ${t} ]
then
echo "x${i};">>${KERNEL_SRC}
else
echo "x${i}, ">>${KERNEL_SRC}
fi
done
# emit outer loop
echo "for (i = 0; i < bm; ++i) {">>${KERNEL_SRC}
# init d0, d1, ..., d(r-1)
for i in `seq 0 $m`
do
echo "d${i} = y[${R} * i + ${i}];">>${KERNEL_SRC}
done
# emit inner loop
echo "for (j = b_row_start[i]; j < b_row_start[i + 1]; ++j, b_values += ${R} * ${C}) {">>${KERNEL_SRC}
# init x0, x1, ..., x(c-1)
for i in `seq 0 $t`
do
echo "x${i} = x[${C} * b_col_idx[j] + ${i}];">>${KERNEL_SRC}
done
# reduce d0, d1, ..., d(r-1)
for i in `seq 0 $t`
do
for j in `seq 0 $m`
do
index=$(( $(( ${j} * ${C} )) + ${i} ))
echo "d${j} += b_values[${index}] * x${i};">>${KERNEL_SRC}
done
done
# write back d0, d1, ..., d(r-1)
for i in `seq 0 $m`
do
echo "y[${R} * i + ${i}] = d${i};">>${KERNEL_SRC}
done
# end inner loop
echo "}">>${KERNEL_SRC}
# end outer loop
echo "}">>${KERNEL_SRC}
}
emit_func_tail() {
echo "}" >> ${KERNEL_SRC}
}
echo "Begin to generate kernel..."
file_gen
for i in `seq 1 12`
do
for j in `seq 1 12`
do
echo ${i} ${j}
emit_func_header ${i} ${j}
emit_func_body ${i} ${j}
emit_func_tail
echo >>${KERNEL_SRC}
done
done
#clang-format -i $KERNEL_SRC
echo "End kernel generating..."
Expect: kernel.cpp with code:
void bcsr_1x1(...) {...}
void bcsr_1x2(...) {...}
...
void bcsr_1x12(...) {...}
void bcsr_2x1(...) {...}
...
void bcsr_2x12(...) {...}
...
void bcsr_12x12(...) {...}
total 144 bcsr subroutines, but the actual output contains negative numbers, e.g.:
bcsr_ - 1x3(...)
Since the core code is:
for i in `seq 1 12`
do
for j in `seq 1 12`
do
echo ${i} ${j}
emit_func_header ${i} ${j}
emit_func_body ${i} ${j}
emit_func_tail
echo >>${KERNEL_SRC}
done
done
The outer loop ranges from 1 to 12 and the inner loop ranges from 1 to 12, its expected output shouldn't contain any negative numbers.
Bash version: GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17) Copyright (C) 2007 Free Software Foundation, Inc.
Upvotes: 0
Views: 389
Reputation: 189628
One of your functions uses the global variable i
and overwrites the value from the main loop.
The quick fix is to add local i
to any function which wants to use this as a local variable, and generally review all functions to make sure all the variables they use are declared local
.
If you don't decide to rewrite this entirely into a language with better scoping rules, I would also suggest that you add proper quoting to all your variables, and examine the redirection rules for shell scripts. In particular, print any diagnostic messages to standard error, and use a single redirection in the main loop.
# Correspondingly refactor file_gen; no need to rm or touch
file_gen >"$KERNEL_SRC"
for i in `seq 1 12`
do
for j in `seq 1 12`
do
echo "$i $j" >&2
emit_func_header "$i" "$j"
emit_func_body "$i" "$j"
emit_func_tail
echo
done
done >>"$KERNEL_SRC"
As long as you are using Bash anyway, you might also want to replace seq
with a traditional three-argument for
loop.
Upvotes: 1
Reputation: 33
It maybe a scope problem, the inner loop called function emit_func_body contains local variable namely i
, when I change the loop index with another name,
everything goes normally:
for _i in `seq 1 12`
do
for _j in `seq 1 12`
do
echo ${_i} ${_j}
emit_func_header ${_i} ${_j}
emit_func_body ${_i} ${_j}
emit_func_tail
echo >>${KERNEL_SRC}
done
done
Upvotes: 0