1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
|
#if HAVE_CONFIG_H
# include "config.h"
#endif
/** @file iterator.h
* @author Sriram Krishnamoorthy
* @brief Stride iterator.
* An iterator for the stride descriptor to reuse common traversal
* functionality. More functionality related to the strided
* descriptor reusable across files will be extracted here as well.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "iterator.h"
/**Create a stride iterator.
* @param base_ptr IN Starting pointer for stride descriptor
* @param stride_levels IN #stride levels
* @param stride_arr IN the strides (arr of size[stride_levels])
* @param seg_count IN #segments in each stride
* level([stride_levels+1])
* @return Handle to stride iterator created
*/
void armci_stride_info_init(stride_info_t *sinfo,
void *base_ptr,
int stride_levels,
const int *stride_arr,
const int *seg_count) {
int i;
assert(sinfo!=NULL);
assert(stride_levels>=0);
assert(stride_levels<=ARMCI_MAX_STRIDE_LEVEL);
for(i=0; i<stride_levels; i++) {
if(i==0)
assert(stride_arr[0] >= seg_count[0]);
else
assert(stride_arr[i] >= stride_arr[i-1]*seg_count[i]);
}
sinfo->base_ptr= base_ptr;
sinfo->stride_levels = stride_levels;
for(i=0; i<stride_levels; i++) {
sinfo->stride_arr[i] = stride_arr[i];
}
for(i=0; i<stride_levels+1; i++) {
sinfo->seg_count[i] = seg_count[i];
}
sinfo->size=1;
for(i=1; i<stride_levels+1; i++) {
sinfo->size *= sinfo->seg_count[i];
}
assert(sinfo->size>0);
sinfo->pos=0;
for(i=0; i<stride_levels+1; i++) {
sinfo->itr[i] = 0;
}
}
/**Destroy a stride iterator.
* @param psitr IN/OUT Pointer to stride iterator
* @return void
*/
void armci_stride_info_destroy(stride_info_t *sinfo) {
}
/**Size of the stride iterator. Defined as total #contiguous
* segments in the stride iterator.
* @param sitr IN Handle to stride iterator
* @return Size of the stride iterator
*/
int armci_stride_info_size(stride_info_t *sinfo) {
assert(sinfo!=NULL);
return sinfo->size;
}
/**Position of the stride iterator. Between 0 and (size-1),
* inclusive. Position is the index of the contiguous segment
* currently traversed by the iterator.
* @param sitr IN Handle to stride descriptor
* @return Position of the iterator
*/
int armci_stride_info_pos(stride_info_t *sinfo) {
assert(sinfo!=NULL);
return sinfo->pos;
}
/**Move the iterator to the next position. Assumes position<=size.
* @param sitr IN Handle to stride descriptor
* @return void
*/
void armci_stride_info_next(stride_info_t *sinfo) {
int i;
assert(sinfo!=NULL);
assert(sinfo->pos <sinfo->size);
sinfo->pos += 1;
if(sinfo->stride_levels>0) {
sinfo->itr[0] += 1;
for(i=0; i<sinfo->stride_levels-1 && sinfo->itr[i]==sinfo->seg_count[i+1]; i++) {
sinfo->itr[i] = 0;
sinfo->itr[i+1] += 1;
}
assert(sinfo->itr[i] <= sinfo->seg_count[i+1]);
}
}
/**Get pointer to the contiguous segment currently being
* traversed. This is the pointer to the user buffer.
* @param sitr IN Handle to stride descriptor
* @return pointer to current contiguous segment
*/
void *armci_stride_info_seg_ptr(stride_info_t *sinfo) {
assert(sinfo!=NULL);
return sinfo->base_ptr + armci_stride_info_seg_off(sinfo);
}
/**Get the size of the current segment.
* @param sitr IN Handle to stride descriptor
* @return Size of the current segment
*/
int armci_stride_info_seg_size(stride_info_t *sinfo) {
assert(sinfo!=NULL);
return sinfo->seg_count[0];
}
/**Get the offset of the current segment with respect to the start of
* the first segment (a.k.a src_ptr)
* @param sitr IN Handle to stride descriptor
* @return Offset of the current segment
*/
int armci_stride_info_seg_off(stride_info_t *sinfo) {
int i;
int off;
assert(sinfo!=NULL);
off=0;
for(i=0; i<sinfo->stride_levels; i++) {
off += sinfo->itr[i] * sinfo->stride_arr[i];
}
return off;
}
/**Check if there are more segments to iterate over. (a.k.a
* position<size).
* @param sitr IN Handle to stride descriptor
* @return Zero if current position is past the size of the
* iterator. Non-zero otherwise.
*/
int armci_stride_info_has_more(stride_info_t *sinfo) {
assert(sinfo!=NULL);
return sinfo->pos<sinfo->size;
}
void armci_write_strided(
void *ptr, int stride_levels, int stride_arr[], int count[], char *buf)
{
const int seg_size = count[0];
int off;
stride_info_t sitr;
off=0;
assert(count[0]>0);
armci_stride_info_init(&sitr,ptr,stride_levels,stride_arr,count);
while(armci_stride_info_has_more(&sitr)) {
char *sptr = armci_stride_info_seg_ptr(&sitr);
memcpy(&buf[off],sptr,seg_size);
off += seg_size;
armci_stride_info_next(&sitr);
}
armci_stride_info_destroy(&sitr);
}
void armci_read_strided(
void *ptr, int stride_levels, int stride_arr[], int count[], char *buf)
{
const int seg_size = count[0];
int off;
stride_info_t sitr;
off=0;
assert(count[0]>0);
armci_stride_info_init(&sitr,ptr,stride_levels,stride_arr,count);
while(armci_stride_info_has_more(&sitr)) {
char *dptr = armci_stride_info_seg_ptr(&sitr);
memcpy(dptr,&buf[off],seg_size);
off += seg_size;
armci_stride_info_next(&sitr);
}
armci_stride_info_destroy(&sitr);
}
|