Другой способ сделать это - поставить
cin.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' );
после того, как ваш cin>>number;
полностью очистит входной буфер (отклонение всех дополнительных символов до тех пор, пока не будет найдена новая строка). Вы должны #include <limits>
получить метод max()
.
Я не рекомендую делать это самостоятельно, если Вы не являетесь довольно опытными с блоком. Используя SSE, более, чем вероятный, потребует тщательной перестройки Ваших данных, как , Skizz указывает, и преимущество часто сомнительно в лучшем случае
для Вас, вероятно, было бы намного лучше записать очень маленькие циклы и сохранить Ваши данные очень плотно организованными и просто полагаться на компилятор, делающий это для Вас. И компилятор C Intel и GCC (начиная с 4.1) могут автовекторизовать Ваш код и вероятно сделают лучшее задание, чем Вы. (Просто добавьте - ftree-векторизуют к Вашему CXXFLAGS.)
Редактирование : Другая вещь, которую я должен упомянуть, состоит в том, что несколько компиляторов поддерживают блок intrinsics , который был бы, вероятно, IMO, быть легче использовать, чем asm () или __ asm {} синтаксис.
Взгляните на встроенный ассемблер для C/C++, вот статья DDJ. Если Вы не будете на 100% уверены, что Ваша программа будет работать на совместимой платформе, необходимо следовать рекомендациям, которые многие дали здесь.
При использовании инструкций SSE Вы, очевидно, ограничены процессорами, которые поддерживают их. Это означает x86, относясь ко времени Pentium приблизительно 2 (не может помнить точно, когда они были представлены, но это давным-давно)
SSE2, который, насколько я могу вспомнить, является тем, который предлагает целочисленные операции, несколько более свежо (Pentium 3? Хотя первые процессоры AMD Athlon не поддерживали их)
В любом случае, у Вас есть две опции для использования этих инструкций. Любая запись весь блок кода в блоке (вероятно, плохая идея. Это делает фактически невозможным для компилятора оптимизировать Ваш код, и человеку очень трудно записать эффективный ассемблер).
, С другой стороны, используют intrinsics доступное с Вашим компилятором (если не изменяет память, они обычно определяются в xmmintrin.h)
, Но снова, производительность не может улучшиться. Код SSE излагает дополнительные требования данных, которые он обрабатывает. Главным образом тот для учета - то, что данные должны быть выровненные на 128-разрядных границах. Должны также быть немногие, или никакие зависимости между значениями, загруженными в тот же регистр (регистр SSE на 128 битов может содержать 4 ints. Добавление первого и второго вместе не оптимально. Но добавление всех четырех ints к соответствующим 4 ints в другом регистре будет быстро)
, может быть заманчиво пользоваться библиотекой, которая обертывает всю игру SSE низкого уровня, но это могло бы также разрушить любой потенциальный выигрыш в производительности.
я не знаю, как поддержка целочисленной операции хорошего SSE, так, чтобы мог также быть фактор, который может ограничить производительность. SSE главным образом предназначен для ускорения операций с плавающей точкой.
Если Вы намереваетесь использовать Microsoft Visual C++, необходимо считать это:
Только для добавления кратко к тому, что было сказано прежде о различных версиях SSE, являющихся доступным на различных центральных процессорах: Это может быть проверено путем рассмотрения соответствующих значений параметра, возвращенных инструкцией CPUID (см., например, документация Intel для деталей).
Напишите код, который помогает компилятору понять то, что Вы делаете. GCC поймет и оптимизирует код SSE, такой как это:
typedef union Vector4f
{
// Easy constructor, defaulted to black/0 vector
Vector4f(float a = 0, float b = 0, float c = 0, float d = 1.0f):
X(a), Y(b), Z(c), W(d) { }
// Cast operator, for []
inline operator float* ()
{
return (float*)this;
}
// Const ast operator, for const []
inline operator const float* () const
{
return (const float*)this;
}
// ---------------------------------------- //
inline Vector4f operator += (const Vector4f &v)
{
for(int i=0; i<4; ++i)
(*this)[i] += v[i];
return *this;
}
inline Vector4f operator += (float t)
{
for(int i=0; i<4; ++i)
(*this)[i] += t;
return *this;
}
// Vertex / Vector
// Lower case xyzw components
struct {
float x, y, z;
float w;
};
// Upper case XYZW components
struct {
float X, Y, Z;
float W;
};
};
Просто не забывают иметь-msse-msse2 на Ваших параметрах сборки!
Хотя верно, что SSE специфичен для некоторых процессоров (SSE2 может быть относительно безопасным, SSE2 намного меньше по моему опыту), вы можете обнаружить CPU во время выполнения и динамически загружать код в зависимости от целевого CPU.
SIMD, которого SSE является примером, позволяет Вам делать ту же операцию на нескольких блоках данных. Так, Вы не получите преимущества для использования SSE как прямая замена для целочисленных операций, Вы только получите преимущества, если можно сделать операции на нескольких элементах данных сразу. Это включает загрузку некоторых значений данных, которые непрерывны в памяти, делая необходимую обработку и затем продвижение в следующий набор значений в массиве.
проблемы:
1, Если путь выполнения кода является иждивенцем на обработанных данных, SIMD становится намного более твердым реализовать. Например:
a = array [index];
a &= mask;
a >>= shift;
if (a < somevalue)
{
a += 2;
array [index] = a;
}
++index;
не легко сделать как SIMD:
a1 = array [index] a2 = array [index+1] a3 = array [index+2] a4 = array [index+3]
a1 &= mask a2 &= mask a3 &= mask a4 &= mask
a1 >>= shift a2 >>= shift a3 >>= shift a4 >>= shift
if (a1<somevalue) if (a2<somevalue) if (a3<somevalue) if (a4<somevalue)
// help! can't conditionally perform this on each column, all columns must do the same thing
index += 4
2, Если данные не непрерывны, тогда загрузка данных в инструкции SIMD громоздкая
3, код является конкретным процессором. SSE находится только на IA32 (Intel/AMD), и не все CPU IA32 поддерживают SSE.
необходимо проанализировать алгоритм и данные, чтобы видеть, может ли это быть SSE'd, и это требует знания, как SSE работает. Существует много документации относительно веб-сайта Intel.
Инструкции SSE были первоначально только на процессорах Intel, но недавно (так как Athlon?) AMD поддерживает их также, поэтому если Вы действительно кодируете против системы команд SSE, необходимо быть портативными к большей части x86 procs.
Однако это не может стоить Вашего времени для изучения кодирования SSE, если Вы не уже знакомы с ассемблером на x86 - более легкая опция могла бы состоять в том, чтобы проверить Ваши документы компилятора и видеть, существуют ли опции позволить компилятору автоматически генерировать код SSE для Вас. Некоторые компиляторы делают очень хорошо векторизующие циклы таким образом. (Вы, вероятно, не удивлены услышать, что компиляторы Intel делают хорошее задание этого:)
Этот вид проблемы является идеальным примером того, где хороший низкоуровневый профилировщик важен. (Что-то как VTune) Это может дать Вам намного более информированную идею того, где Ваши горячие точки лежат.
Мое предположение, от того, что Вы описываете, - то, что Ваша горячая точка, вероятно, будет отказами предсказания ветвлений, следующими из минуты / макс. использования вычислений если/еще. Поэтому использование SIMD intrinsics должно позволить Вам использовать минимальные инструкции / макс. инструкции, однако, могло бы стоить просто попытаться использовать минуту без веток / макс. caluculation вместо этого. Это могло бы достигнуть большинства усилений с меньшим количеством боли.
Что-то вроде этого:
inline int
minimum(int a, int b)
{
int mask = (a - b) >> 31;
return ((a & mask) | (b & ~mask));
}
Мы реализовали некоторый код обработки изображений, подобный тому, что Вы описываете, но на массиве байтов В SSE. Ускорение по сравнению с кодом C значительно, в зависимости от точного алгоритма больше, чем фактор 4, даже относительно компилятора Intel. Однако, поскольку Вы уже упомянули, что у Вас есть следующие недостатки:
Мобильность. Код будет работать на каждом подобном Intel ЦП, так также AMD, но не на других центральных процессорах. Это не проблема для нас, потому что мы управляем целевыми аппаратными средствами. Переключение компиляторов и даже к ОС на 64 бита может также быть проблемой.
у Вас есть крутая кривая обучения, но я нашел, что после схватывания, принципы, пишущий новые алгоритмы не являются этим трудно.
Пригодность для обслуживания. Большая часть C или программисты на C++ не знают о блоке/SSE.
Мой совет Вам будет состоять в том, чтобы пойти для него, только если Вам действительно нужно повышение производительности, и Вы не можете найти функцию для своей проблемы в библиотеке как Intel IPP, и если можно жить с проблемами мобильности.
SIMD intrinsics (такой как SSE2) может ускорить этот вид вещи, но взять экспертные знания для использования правильно. Они очень чувствительны к выравниванию и конвейерно обрабатывают задержку; небрежное использование может сделать производительность еще хуже, чем это было бы без них. Вы заставите намного более легкое и больше непосредственного ускорения от простого использования упреждающей выборки кэша удостоверяться, что все Ваши ints находятся в L1 как раз к Вам для работы на них.
, Если для Вашей функции не нужна пропускная способность лучше, чем 100 000 000 целых чисел в секунду, SIMD, вероятно, не стоит проблемы Вам.
Из своего опыта могу сказать, что SSE дает огромное (в 4 раза и выше) ускорение по сравнению с простой версией кода на Си (без встроенного asm, без использования intrinsics), но оптимизированный вручную ассемблер может победить ассемблер, сгенерированный компилятором, если компилятор не может понять, что задумал программист (поверьте мне, компиляторы не покрывают все возможные комбинации кода и никогда не покроют). И еще, компилятор не может каждый раз компоновать данные так, чтобы они выполнялись с максимально возможной скоростью. Но вам нужен большой опыт для увеличения скорости по сравнению с Intel-компилятором (если это возможно).