Example #1
0
void RandomPermuter::subset_epoch(
      vector<epoch_op>::iterator &res_start,
      vector<epoch_op>::iterator &res_end,
      epoch &epoch) {

  unsigned int req_size = distance(res_start, res_end);
  assert(req_size <= epoch.ops.size());

  // Even if the number of bios we're placing is less than the number in the
  // epoch, allow any bio but the barrier (if present) to be picked.
  unsigned int slots = epoch.ops.size();
  if (epoch.has_barrier) {
    --slots;
  }

  // Bitmap to indicate which bios in the epoch we want to pick for the crash
  // state.
  vector<unsigned int> epoch_op_bitmap(epoch.ops.size());

  // Fill the list with the empty slots, either [0, epoch.size() - 1] or
  // [0, epoch.size() - 2]. Prefer a list so that removals are fast. We have
  // this so that each time we shuffle the indexes of bios in the epoch, and
  // pick the first req_size number of bios.

  vector<unsigned int> indices(slots);
  iota(indices.begin(), indices.end(), 0);
  // Use a known random generator function for repeatability.
  std::random_shuffle(indices.begin(), indices.end(), subset_random_);

  // Populate the bitmap to set req_set number of bios.
  for (int i = 0; i < req_size; i++) {
    epoch_op_bitmap[indices[i]] = 1;
  }

  // Return the bios corresponding to bitmap indexes.
  for (unsigned int filled = 0;
      filled < epoch_op_bitmap.size() && res_start != res_end; filled++) {
    if (epoch_op_bitmap[filled] == 1) {
      *res_start = epoch.ops.at(filled);
      ++res_start;
    }
  }

  // We are only placing part of an epoch so we need to return here.
  if (res_start == res_end) {
    return;
  }

  assert(epoch.has_barrier);

  // Place the barrier operation if it exists since the entire vector already
  // exists (i.e. we won't cause extra shifting when adding the other elements).
  // Decrement out count of empty slots since we have filled one.
  *res_start = epoch.ops.back();
}
void random_iota(I first, I last) {
  iota(first, last, 0);
  std::random_shuffle(first, last);
}
Example #3
0
bool RandomPermuter::gen_one_sector_state(vector<DiskWriteData> &res,
    PermuteTestResult &log_data) {
  res.clear();
  // Return if there are no ops to work with.
  if (GetEpochs()->size() == 0) {
    return false;
  }

  vector<epoch> *epochs = GetEpochs();

  // Pick the point in the sequence we will crash at.
  // Find how many elements we will be returning (randomly determined).
  uniform_int_distribution<unsigned int> permute_epochs(1, epochs->size());
  unsigned int num_epochs = permute_epochs(rand);
  unsigned int num_requests = 0;
  if (!epochs->at(num_epochs - 1).ops.empty()) {
    // It is not valid to call the random number generator with arguments (1, 0)
    // (you get a large number if you do), so skip this if the epoch we crash in
    // has no ops in it.

    // Don't subtract 1 from this size so that we can send a complete epoch if
    // we want.
    uniform_int_distribution<unsigned int> permute_requests(1,
        epochs->at(num_epochs - 1).ops.size());
    num_requests = permute_requests(rand);
  }

  // Tell CrashMonkey the most recently seen checkpoint for the crash state
  // we're generating. We can't just pull the last epoch because it could be the
  // case that there's a checkpoint at the end of this disk write epoch.
  // Therefore, we should determine 1. if we are writing out this entire epoch,
  // and 2. if the checkpoint epoch for this disk write epoch is different than
  // the checkpoint epoch of the disk write epoch before this one (indicating
  // that this disk write epoch changes checkpoint epochs).
  epoch *target = &(epochs->at(num_epochs - 1));
  epoch *prev = NULL;
  if (num_epochs > 1) {
    prev = &epochs->at(num_epochs - 2);
  }
  if (num_requests != target->ops.size()) {
    log_data.last_checkpoint = (prev) ? prev->checkpoint_epoch : 0;
  } else {
    log_data.last_checkpoint = target->checkpoint_epoch;
  }

  // Get and coalesce the sectors of the final epoch we crashed in. We do this
  // here so that we can determine the size of the resulting crash state and
  // allocate that many slots in `res` right off the bat, thus skipping later
  // reallocations as the vector grows.
  vector<EpochOpSector> final_epoch;
  for (unsigned int i = 0; i < num_requests; ++i) {
    vector<EpochOpSector> sectors =
      epochs->at(num_epochs - 1).ops.at(i).ToSectors(sector_size_);
    final_epoch.insert(final_epoch.end(), sectors.begin(), sectors.end());
  }

  unsigned int total_elements = 0;
  for (unsigned int i = 0; i < num_epochs - 1; ++i) {
    total_elements += epochs->at(i).ops.size();
  }

  if (final_epoch.empty()) {
    // No sectors to drop in the final epoch.
    res.resize(total_elements);
    auto epoch_end_iterator = epochs->begin() + num_epochs - 1;
    AddEpochs(res.begin(), res.end(), epochs->begin(), epoch_end_iterator);
    return true;
  } else if (num_requests == epochs->at(num_epochs - 1).ops.size() &&
      epochs->at(num_epochs - 1).ops.back().op.is_barrier()) {
    // We picked the entire epoch and it has a barrier, so we can't rearrange
    // anything.
    res.resize(total_elements + epochs->at(num_epochs - 1).ops.size());
    // + 1 because we also add the full epoch we "crash" in.
    auto epoch_end_iterator = epochs->begin() + num_epochs;
    AddEpochs(res.begin(), res.end(), epochs->begin(), epoch_end_iterator);
    return true;
  }

  // For this branch of execution, we are dropping some sectors from the final
  // epoch we are "crashing" in.

  // Pick a number of sectors to keep. final_epoch.size() > 0 due to if block
  // above, so no need to worry about getting an invalid range.
  uniform_int_distribution<unsigned int> rand_num_sectors(1,
      final_epoch.size());
  const unsigned int num_sectors = rand_num_sectors(rand);

  final_epoch = CoalesceSectors(final_epoch);

  // Result size is now a known quantity.
  res.resize(total_elements + num_sectors);
  // Add the requests not in the final epoch to the result.
  auto epoch_end_iterator = epochs->begin() + (num_epochs - 1);
  auto res_end = res.begin() + total_elements;
  AddEpochs(res.begin(), res_end, epochs->begin(), epoch_end_iterator);

  // Randomly drop some sectors.
  vector<unsigned int> indices(final_epoch.size());
  iota(indices.begin(), indices.end(), 0);
  // Use a known random generator function for repeatability.
  std::random_shuffle(indices.begin(), indices.end(), subset_random_);

  // Populate the bitmap to set req_set number of bios. This is required to keep
  // sectors in temporal order when we generate the crash state.
  vector<unsigned char> sector_bitmap(final_epoch.size());
  for (int i = 0; i < num_sectors; ++i) {
    sector_bitmap[indices[i]] = 1;
  }

  // Add the sectors corresponding to bitmap indexes to the result.
  auto next_index = res.begin() + total_elements;
  for (unsigned int i = 0; i < sector_bitmap.size(); ++i) {
    if (next_index == res.end()) {
      break;
    }
    if (sector_bitmap[i] == 1) {
      *next_index = final_epoch.at(i).ToWriteData();
      ++next_index;
    }
  }

  return true;
}
void KDTree::build(const Spheres& spheres)
{
	leaves = 0;
	this->spheres = spheres;
	sceneBBox = createBoundingBox(spheres);

	int axis = static_cast<int>(AXIS_X);

	KDNode root;
	nodes.push_back(root);

	StackNode stackNode;
	stackNode.bbox = sceneBBox;
	stackNode.nodeIdx = nodes.size() - 1;
	stackNode.sphereIndices.resize(spheres.count);
	iota(stackNode.sphereIndices.begin(), stackNode.sphereIndices.end(), 0);

	stack<StackNode> st;
	st.push(stackNode);

	while(!st.empty())
	{
		StackNode stackNode = st.top();
		st.pop();

		if(stackNode.sphereIndices.size() <= maxSpheresInLeaf || nodes.size() >= maxNodes)
		{
			leavesChildren.push_back(stackNode.sphereIndices);
			initLeafNode(stackNode.nodeIdx, leavesChildren.size() - 1);
			++leaves;
			continue;
		}

		axis = axis % 3;
		float leftLimit = stackNode.bbox.vmin[axis];
		float rightLimit = stackNode.bbox.vmax[axis];

		float splitPos = (leftLimit + rightLimit) * 0.5f; // TODO use SAH

		Axis splitAxis = static_cast<Axis>(axis);

		StackNode child1StackNode, child2StackNode;
		nodes.push_back(KDNode());
		child1StackNode.nodeIdx = nodes.size() - 1;
		nodes.push_back(KDNode());
		child2StackNode.nodeIdx = nodes.size() - 1;

		stackNode.bbox.split(splitAxis, splitPos, child1StackNode.bbox, child2StackNode.bbox);

		for(int i = 0; i < stackNode.sphereIndices.size(); ++i)
		{
			if(spheres.centerCoords[axis][stackNode.sphereIndices[i]] < splitPos)
			{
				child1StackNode.sphereIndices.push_back(stackNode.sphereIndices[i]);
			}
			else
			{
				child2StackNode.sphereIndices.push_back(stackNode.sphereIndices[i]);
			}
		}
		initInnerNode(stackNode.nodeIdx, splitAxis, splitPos, child1StackNode.nodeIdx);
		st.push(child2StackNode);
		st.push(child1StackNode);

		axis += 1;
	}
}